feat(): Introduce translation module and preliminary application of them (#14189)
* feat(): Translation first steps * feat(): locale middleware * feat(): readonly links * feat(): feature flag * feat(): modules sdk * feat(): translation module re export * start adding workflows * update typings * update typings * test(): Add integration tests * test(): centralize filters preparation * test(): centralize filters preparation * remove unnecessary importy * fix workflows * Define StoreLocale inside Store Module * Link definition to extend Store with supported_locales * store_locale migration * Add supported_locales handling in Store Module * Tests * Accept supported_locales in Store endpoints * Add locales to js-sdk * Include locale list and default locale in Store Detail section * Initialize local namespace in js-sdk * Add locales route * Make code primary key of locale table to facilitate upserts * Add locales routes * Show locale code as is * Add list translations api route * Batch endpoint * Types * New batchTranslationsWorkflow and various updates to existent ones * Edit default locale UI * WIP * Apply translation agnostically * middleware * Apply translation agnostically * fix Apply translation agnostically * apply translations to product list * Add feature flag * fetch translations by batches of 250 max * fix apply * improve and test util * apply to product list * dont manage translations if no locale * normalize locale * potential todo * Protect translations routes with feature flag * Extract normalize locale util to core/utils * Normalize locale on write * Normalize locale for read * Use feature flag to guard translations UI across the board * Avoid throwing incorrectly when locale_code not present in partial updates * move applyTranslations util * remove old tests * fix util tests * fix(): product end points * cleanup * update lock * remove unused var * cleanup * fix apply locale * missing new dep for test utils * Change entity_type, entity_id to reference, reference_id * Remove comment * Avoid registering translations route if ff not enabled * Prevent registering express handler for disabled route via defineFileConfig * Add tests * Add changeset * Update test * fix integration tests, module and internals * Add locale id plus fixed * Allow to pass array of reference_id * fix unit tests * fix link loading * fix store route * fix sales channel test * fix tests --------- Co-authored-by: Nicolas Gorga <nicogorga11@gmail.com> Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
fea3d4ec49
commit
6dc0b8bed8
@@ -0,0 +1,172 @@
|
||||
import { normalizeLocale } from "../normalize-locale"
|
||||
|
||||
describe("normalizeLocale", function () {
|
||||
it("should normalize single segment locales to lowercase", function () {
|
||||
const expectations = [
|
||||
{
|
||||
input: "eN",
|
||||
output: "en",
|
||||
},
|
||||
{
|
||||
input: "EN",
|
||||
output: "en",
|
||||
},
|
||||
{
|
||||
input: "En",
|
||||
output: "en",
|
||||
},
|
||||
{
|
||||
input: "en",
|
||||
output: "en",
|
||||
},
|
||||
{
|
||||
input: "fr",
|
||||
output: "fr",
|
||||
},
|
||||
{
|
||||
input: "FR",
|
||||
output: "fr",
|
||||
},
|
||||
{
|
||||
input: "de",
|
||||
output: "de",
|
||||
},
|
||||
]
|
||||
|
||||
expectations.forEach((expectation) => {
|
||||
expect(normalizeLocale(expectation.input)).toEqual(expectation.output)
|
||||
})
|
||||
})
|
||||
|
||||
it("should normalize two segment locales (language-region)", function () {
|
||||
const expectations = [
|
||||
{
|
||||
input: "en-Us",
|
||||
output: "en-US",
|
||||
},
|
||||
{
|
||||
input: "EN-US",
|
||||
output: "en-US",
|
||||
},
|
||||
{
|
||||
input: "en-us",
|
||||
output: "en-US",
|
||||
},
|
||||
{
|
||||
input: "En-Us",
|
||||
output: "en-US",
|
||||
},
|
||||
{
|
||||
input: "fr-FR",
|
||||
output: "fr-FR",
|
||||
},
|
||||
{
|
||||
input: "FR-fr",
|
||||
output: "fr-FR",
|
||||
},
|
||||
{
|
||||
input: "de-DE",
|
||||
output: "de-DE",
|
||||
},
|
||||
{
|
||||
input: "es-ES",
|
||||
output: "es-ES",
|
||||
},
|
||||
{
|
||||
input: "pt-BR",
|
||||
output: "pt-BR",
|
||||
},
|
||||
]
|
||||
|
||||
expectations.forEach((expectation) => {
|
||||
expect(normalizeLocale(expectation.input)).toEqual(expectation.output)
|
||||
})
|
||||
})
|
||||
|
||||
it("should normalize three segment locales (language-script-region)", function () {
|
||||
const expectations = [
|
||||
{
|
||||
input: "RU-cYrl-By",
|
||||
output: "ru-Cyrl-BY",
|
||||
},
|
||||
{
|
||||
input: "ru-cyrl-by",
|
||||
output: "ru-Cyrl-BY",
|
||||
},
|
||||
{
|
||||
input: "RU-CYRL-BY",
|
||||
output: "ru-Cyrl-BY",
|
||||
},
|
||||
{
|
||||
input: "zh-Hans-CN",
|
||||
output: "zh-Hans-CN",
|
||||
},
|
||||
{
|
||||
input: "ZH-HANS-CN",
|
||||
output: "zh-Hans-CN",
|
||||
},
|
||||
{
|
||||
input: "sr-Latn-RS",
|
||||
output: "sr-Latn-RS",
|
||||
},
|
||||
{
|
||||
input: "SR-LATN-RS",
|
||||
output: "sr-Latn-RS",
|
||||
},
|
||||
]
|
||||
|
||||
expectations.forEach((expectation) => {
|
||||
expect(normalizeLocale(expectation.input)).toEqual(expectation.output)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return locale as-is for more than three segments", function () {
|
||||
const expectations = [
|
||||
{
|
||||
input: "en-US-x-private",
|
||||
output: "en-US-x-private",
|
||||
},
|
||||
{
|
||||
input: "en-US-x-private-extended",
|
||||
output: "en-US-x-private-extended",
|
||||
},
|
||||
{
|
||||
input: "en-US-x-private-extended-more",
|
||||
output: "en-US-x-private-extended-more",
|
||||
},
|
||||
]
|
||||
|
||||
expectations.forEach((expectation) => {
|
||||
expect(normalizeLocale(expectation.input)).toEqual(expectation.output)
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle edge cases", function () {
|
||||
const expectations = [
|
||||
{
|
||||
input: "",
|
||||
output: "",
|
||||
},
|
||||
{
|
||||
input: "a",
|
||||
output: "a",
|
||||
},
|
||||
{
|
||||
input: "A",
|
||||
output: "a",
|
||||
},
|
||||
{
|
||||
input: "a-B",
|
||||
output: "a-B",
|
||||
},
|
||||
{
|
||||
input: "a-b-C",
|
||||
output: "a-B-C",
|
||||
},
|
||||
]
|
||||
|
||||
expectations.forEach((expectation) => {
|
||||
expect(normalizeLocale(expectation.input)).toEqual(expectation.output)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -185,6 +185,9 @@ function resolveModules(
|
||||
{ resolve: MODULE_PACKAGE_NAMES[Modules.ORDER] },
|
||||
{ resolve: MODULE_PACKAGE_NAMES[Modules.SETTINGS] },
|
||||
|
||||
// TODO: re-enable this once we have the final release
|
||||
// { resolve: MODULE_PACKAGE_NAMES[Modules.TRANSLATION] },
|
||||
|
||||
{
|
||||
resolve: MODULE_PACKAGE_NAMES[Modules.AUTH],
|
||||
options: {
|
||||
|
||||
@@ -53,6 +53,7 @@ export * from "./medusa-container"
|
||||
export * from "./merge-metadata"
|
||||
export * from "./merge-plugin-modules"
|
||||
export * from "./normalize-csv-value"
|
||||
export * from "./normalize-locale"
|
||||
export * from "./normalize-import-path-with-source"
|
||||
export * from "./object-from-string-path"
|
||||
export * from "./object-to-string-path"
|
||||
|
||||
40
packages/core/utils/src/common/normalize-locale.ts
Normal file
40
packages/core/utils/src/common/normalize-locale.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { upperCaseFirst } from "./upper-case-first"
|
||||
|
||||
/**
|
||||
* Normalizes a locale string to {@link https://developer.mozilla.org/en-US/docs/Glossary/BCP_47_language_tag|BCP 47 language tag format}
|
||||
* @param locale - The locale string to normalize
|
||||
* @returns The normalized locale string
|
||||
*
|
||||
* @example
|
||||
* input: "en-Us"
|
||||
* output: "en-US"
|
||||
*
|
||||
* @example
|
||||
* input: "eN"
|
||||
* output: "en"
|
||||
*
|
||||
* @example
|
||||
* input: "RU-cYrl-By"
|
||||
* output: "ru-Cyrl-BY"
|
||||
*/
|
||||
export function normalizeLocale(locale: string) {
|
||||
const segments = locale.split("-")
|
||||
|
||||
if (segments.length === 1) {
|
||||
return segments[0].toLowerCase()
|
||||
}
|
||||
|
||||
// e.g en-US
|
||||
if (segments.length === 2) {
|
||||
return `${segments[0].toLowerCase()}-${segments[1].toUpperCase()}`
|
||||
}
|
||||
|
||||
// e.g ru-Cyrl-BY
|
||||
if (segments.length === 3) {
|
||||
return `${segments[0].toLowerCase()}-${upperCaseFirst(
|
||||
segments[1].toLowerCase()
|
||||
)}-${segments[2].toUpperCase()}`
|
||||
}
|
||||
|
||||
return locale
|
||||
}
|
||||
Reference in New Issue
Block a user