diff --git a/packages/visual-editor/src/components/pageSections/ReviewsSection/ReviewsSection.test.tsx b/packages/visual-editor/src/components/pageSections/ReviewsSection/ReviewsSection.test.tsx index 09ba339e2..408dc8c90 100644 --- a/packages/visual-editor/src/components/pageSections/ReviewsSection/ReviewsSection.test.tsx +++ b/packages/visual-editor/src/components/pageSections/ReviewsSection/ReviewsSection.test.tsx @@ -330,16 +330,11 @@ describe("ReviewsSection", async () => { streamDocument: document, }); - const templateProps = { - document: document, - data: data, - }; - - const updatedData = await injectTranslations(templateProps); + const translations = await injectTranslations(document); const { container } = reactRender( - - + + ); diff --git a/packages/visual-editor/src/utils/i18n/components.ts b/packages/visual-editor/src/utils/i18n/components.ts index eef6d39f3..8e847ec1b 100644 --- a/packages/visual-editor/src/utils/i18n/components.ts +++ b/packages/visual-editor/src/utils/i18n/components.ts @@ -1,5 +1,8 @@ import i18next from "i18next"; import { initReactI18next } from "react-i18next"; +import { getTranslations } from "./getTranslations"; +import { StreamDocument } from "../applyTheme"; +import { normalizeLocalesInObject } from "../normalizeLocale"; const NAMESPACE = "visual-editor"; @@ -28,55 +31,18 @@ export interface TemplateProps { * by consumers of visual-editor in transformProps of a template. */ export const injectTranslations = async ( - templateProps: TemplateProps -): Promise => { - if (!templateProps?.document?.locale) { - return templateProps; - } - - const translations = - (await getTranslations(templateProps?.document?.locale)) || {}; - - return { - ...templateProps, - translations, - }; -}; - -/** - * Dynamically imports the translation file for the given locale. - */ -const getTranslations = async ( - locale: string, - isRetry = false -): Promise> => { - if (!locale) { + streamDocument: StreamDocument +): Promise | Record> => { + if (!streamDocument?.locale) { return {}; } - try { - const module = await import( - `../../../locales/components/${locale}/visual-editor.json` - ); - return module.default; - } catch (e) { - if (isRetry || locale === "en") { - console.error( - "Error loading translations for locale", - locale, - e, - "No fallback available." - ); - return {}; - } - console.error( - "Error loading translations for locale", - locale, - e, - "Falling back to en." - ); - return getTranslations("en", true); - } + return ( + (await getTranslations( + normalizeLocalesInObject(streamDocument).locale, + "components" + )) || {} + ); }; /** @@ -92,7 +58,8 @@ export const loadComponentTranslations = async ( return; } - const translationsToInject = translations || (await getTranslations(locale)); + const translationsToInject = + translations || (await getTranslations(locale, "components")); if (translationsToInject && Object.keys(translationsToInject).length > 0) { i18nComponentsInstance.addResourceBundle( diff --git a/packages/visual-editor/src/utils/i18n/fallbacks.ts b/packages/visual-editor/src/utils/i18n/fallbacks.ts deleted file mode 100644 index e38743927..000000000 --- a/packages/visual-editor/src/utils/i18n/fallbacks.ts +++ /dev/null @@ -1,43 +0,0 @@ -type Fallback = { - from: string; - to: string; -}; - -export const defaultI18nFallbacks: Fallback[] = [ - { - from: "en-US", - to: "en", - }, - { - from: "zh-Hans", - to: "zh", - }, - { - from: "zh-Hant", - to: "zh-TW", - }, -]; - -/** - * Applies language fallbacks to i18n resources - * ex: "zh-Hans" to "zh" and "zh-Hant" to "zh-TW" - * - * These fallbacks occur BEFORE fallbackLng in - * i18n configuration - * @param resources the resources to modify - * @param fallbacks map of fallback languages - */ -export const applyI18nFallbacks = ( - resources: Record, - fallbacks: Fallback[] -) => { - fallbacks.forEach(({ from, to }: Fallback) => { - if (resources[from]) { - return; - } - if (!resources[to]) { - return; - } - resources[from] = resources[to]; - }); -}; diff --git a/packages/visual-editor/src/utils/i18n/getTranslations.ts b/packages/visual-editor/src/utils/i18n/getTranslations.ts new file mode 100644 index 000000000..b8e13d36c --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/getTranslations.ts @@ -0,0 +1,46 @@ +const supportedRegionalLocales = ["en-GB", "zh-TW"]; + +/** + * Dynamically imports the translation file for the given locale. + */ +export const getTranslations = async ( + locale: string, + instance: "platform" | "components", + isRetry = false +): Promise> => { + if (!locale) { + return {}; + } + + let strippedLocale = locale; + if (!supportedRegionalLocales.includes(locale)) { + strippedLocale = locale.split("-")[0]; + } + if (locale.includes("zh-Hant")) { + strippedLocale = "zh-TW"; + } + + try { + const module = await import( + `../../../locales/${instance}/${strippedLocale}/visual-editor.json` + ); + return module.default; + } catch (e) { + if (isRetry || strippedLocale === "en") { + console.error( + `Error loading ${instance} translations for locale`, + locale, + e, + "No fallback available." + ); + return {}; + } + console.error( + `Error loading ${instance} translations for locale`, + locale, + e, + "Falling back to en." + ); + return getTranslations("en", instance, true); + } +}; diff --git a/packages/visual-editor/src/utils/i18n/platform.ts b/packages/visual-editor/src/utils/i18n/platform.ts index 2983b42e5..7c447e9ba 100644 --- a/packages/visual-editor/src/utils/i18n/platform.ts +++ b/packages/visual-editor/src/utils/i18n/platform.ts @@ -1,6 +1,6 @@ import i18next, { TOptions } from "i18next"; import { initReactI18next, useTranslation } from "react-i18next"; -import { applyI18nFallbacks, defaultI18nFallbacks } from "./fallbacks.ts"; +import { getTranslations } from "./getTranslations.ts"; const NAMESPACE = "visual-editor"; @@ -16,42 +16,6 @@ i18nPlatformInstance.use(initReactI18next).init({ resources: {}, }); -/** - * Dynamically imports the translation file for the given locale. - */ -const getTranslations = async ( - locale: string, - isRetry = false -): Promise> => { - if (!locale) { - return {}; - } - - try { - const module = await import( - `../../../locales/platform/${locale}/visual-editor.json` - ); - return module.default; - } catch (e) { - if (isRetry || locale === "en") { - console.error( - "Error loading translations for locale", - locale, - e, - "No fallback available." - ); - return {}; - } - console.error( - "Error loading translations for locale", - locale, - e, - "Falling back to en." - ); - return getTranslations("en", true); - } -}; - /** * Loads translations into the i18n instance for the given locale. */ @@ -60,8 +24,7 @@ export const loadPlatformTranslations = async (locale: string) => { return; } - const translationsToInject = await getTranslations(locale); - applyI18nFallbacks(translationsToInject, defaultI18nFallbacks); + const translationsToInject = await getTranslations(locale, "platform"); if (translationsToInject && Object.keys(translationsToInject).length > 0) { i18nPlatformInstance.addResourceBundle( diff --git a/packages/visual-editor/src/vite-plugin/templates/directory.tsx b/packages/visual-editor/src/vite-plugin/templates/directory.tsx index 64f712fb1..89fddc324 100644 --- a/packages/visual-editor/src/vite-plugin/templates/directory.tsx +++ b/packages/visual-editor/src/vite-plugin/templates/directory.tsx @@ -106,19 +106,19 @@ export const getPath: GetPath = ({ document }) => { export const transformProps: TransformProps = async (props) => { const { document } = props; + const migratedData = migrate( JSON.parse(document.__.layout), migrationRegistry, directoryConfig, document ); - const updatedData = await injectTranslations( - await resolveAllData(migratedData, directoryConfig, { - streamDocument: document, - }) - ); + const resolvedPuckData = await resolveAllData(migratedData, directoryConfig, { + streamDocument: document, + }); + const translations = await injectTranslations(document); - return { ...props, data: updatedData }; + return { ...props, data: resolvedPuckData, translations }; }; const Directory: Template = (props) => { diff --git a/packages/visual-editor/src/vite-plugin/templates/locator.tsx b/packages/visual-editor/src/vite-plugin/templates/locator.tsx index 4ac7ed2ff..9cba7116e 100644 --- a/packages/visual-editor/src/vite-plugin/templates/locator.tsx +++ b/packages/visual-editor/src/vite-plugin/templates/locator.tsx @@ -107,19 +107,19 @@ export const getPath: GetPath = ({ document }) => { export const transformProps: TransformProps = async (props) => { const { document } = props; + const migratedData = migrate( JSON.parse(document.__.layout), migrationRegistry, locatorConfig, document ); - const updatedData = await injectTranslations( - await resolveAllData(migratedData, locatorConfig, { - streamDocument: document, - }) - ); + const resolvedPuckData = await resolveAllData(migratedData, locatorConfig, { + streamDocument: document, + }); + const translations = await injectTranslations(document); - return { ...props, data: updatedData }; + return { ...props, data: resolvedPuckData, translations }; }; const Locator: Template = (props) => { diff --git a/packages/visual-editor/src/vite-plugin/templates/main.tsx b/packages/visual-editor/src/vite-plugin/templates/main.tsx index 8edb60212..a8be714d9 100644 --- a/packages/visual-editor/src/vite-plugin/templates/main.tsx +++ b/packages/visual-editor/src/vite-plugin/templates/main.tsx @@ -105,23 +105,24 @@ export const getPath: GetPath = ({ export const transformProps: TransformProps = async (props) => { const { document } = props; + const migratedData = migrate( JSON.parse(document.__.layout), migrationRegistry, mainConfig, document ); - const updatedData = await injectTranslations( - await resolveAllData(migratedData, mainConfig, { - streamDocument: document, - }) - ); + const resolvedPuckData = await resolveAllData(migratedData, mainConfig, { + streamDocument: document, + }); + const translations = await injectTranslations(document); - return { ...props, data: updatedData }; + return { ...props, data: resolvedPuckData, translations }; }; const Location: Template = (props) => { const { document, data } = props; + const filteredConfig = filterComponentsFromConfig( mainConfig, document?._additionalLayoutComponents, diff --git a/starter/src/templates/dev.tsx b/starter/src/templates/dev.tsx index ac93f761b..459795e7b 100644 --- a/starter/src/templates/dev.tsx +++ b/starter/src/templates/dev.tsx @@ -133,7 +133,8 @@ export const getHeadConfig: GetHeadConfig = ( export const transformProps: TransformProps> = async ( data, ) => { - return await injectTranslations(data); + const translations = await injectTranslations(data.document); + return { ...data, translations }; }; export const getPath: GetPath = ({ document }) => { diff --git a/yext-visual-editor-1.0.5test3.tgz b/yext-visual-editor-1.0.5test3.tgz deleted file mode 100644 index ccbcfe8df..000000000 Binary files a/yext-visual-editor-1.0.5test3.tgz and /dev/null differ