From e4a842f066d464ca6f8b1826aece3b98ca9a8357 Mon Sep 17 00:00:00 2001 From: Lukas Obermann Date: Tue, 3 Oct 2023 20:54:56 +0200 Subject: [PATCH] feat: support translations that vary by operating system --- src/main/index.ts | 1 + src/main_window/index.tsx | 1 + src/settings_window/index.tsx | 1 + .../LocalizationProvider.tsx | 4 ++- src/shared/contexts/localization.ts | 2 ++ src/shared/hooks/translate.ts | 2 ++ src/shared/utils/translate.ts | 28 +++++++++++++++---- src/updater_window/index.tsx | 1 + 8 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index d71078cf..b5c516c8 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -37,6 +37,7 @@ const setMenu = (database: Database) => { Object.fromEntries(database.raw.locales), getGlobalSettings().locale, app.getLocale(), + process.platform, ) const template: MenuItemConstructorOptions[] = [ diff --git a/src/main_window/index.tsx b/src/main_window/index.tsx index b6213414..cd517cda 100644 --- a/src/main_window/index.tsx +++ b/src/main_window/index.tsx @@ -176,6 +176,7 @@ ExternalAPI.on("initial-setup", ({ database, globalSettings }) => { selectedFallbackLocale={globalSettings.fallbackLocale} selectedLocaleEvents={ExternalAPI} systemLocale={ExternalAPI.systemLocale} + platform={ExternalAPI.platform} locales={Object.fromEntries(database.raw.locales)} ui={Object.fromEntries(database.raw.ui)} > diff --git a/src/settings_window/index.tsx b/src/settings_window/index.tsx index 5e53c820..cb209c16 100644 --- a/src/settings_window/index.tsx +++ b/src/settings_window/index.tsx @@ -18,6 +18,7 @@ ExternalAPI.on("initial-setup", ({ translations, locales, systemLocale, settings selectedFallbackLocale={settings.fallbackLocale} selectedLocaleEvents={ExternalAPI} systemLocale={systemLocale} + platform={ExternalAPI.platform} locales={locales} ui={translations} > diff --git a/src/shared/components/localizationProvider/LocalizationProvider.tsx b/src/shared/components/localizationProvider/LocalizationProvider.tsx index 6289cf9e..159ac6c0 100644 --- a/src/shared/components/localizationProvider/LocalizationProvider.tsx +++ b/src/shared/components/localizationProvider/LocalizationProvider.tsx @@ -13,6 +13,7 @@ type Props = { "fallback-locale-changed": [locale: string | undefined] }> systemLocale: string + platform: NodeJS.Platform locales: Record ui: Record } @@ -25,6 +26,7 @@ export const LocalizationProvider: FCC = props => { const { children, locales, + platform, selectedLocale: initialSelectedLocale, selectedFallbackLocale: initialSelectedFallbackLocale, selectedLocaleEvents, @@ -49,7 +51,7 @@ export const LocalizationProvider: FCC = props => { return ( {children} diff --git a/src/shared/contexts/localization.ts b/src/shared/contexts/localization.ts index 90eadc77..6bdd4536 100644 --- a/src/shared/contexts/localization.ts +++ b/src/shared/contexts/localization.ts @@ -10,6 +10,7 @@ export type LocalizationContext = { selectedLocale: string | undefined selectedFallbackLocale: string | undefined systemLocale: string + platform: NodeJS.Platform locales: Record ui: Record } @@ -23,6 +24,7 @@ export const LocalizationContext = createContext({ selectedLocale: undefined, selectedFallbackLocale: undefined, systemLocale: "en-US", + platform: "win32", locales: {}, ui: {}, }) diff --git a/src/shared/hooks/translate.ts b/src/shared/hooks/translate.ts index 48960634..dd3d0b30 100644 --- a/src/shared/hooks/translate.ts +++ b/src/shared/hooks/translate.ts @@ -16,12 +16,14 @@ export const useTranslate = () => { localizationContext.locales, localizationContext.selectedLocale, localizationContext.systemLocale, + localizationContext.platform, ), [ localizationContext.locales, localizationContext.selectedLocale, localizationContext.systemLocale, localizationContext.ui, + localizationContext.platform, ], ) diff --git a/src/shared/utils/translate.ts b/src/shared/utils/translate.ts index 9e64b969..67cbd926 100644 --- a/src/shared/utils/translate.ts +++ b/src/shared/utils/translate.ts @@ -1,6 +1,6 @@ import { Locale } from "optolith-database-schema/types/Locale" import { UI } from "optolith-database-schema/types/UI" -import { PluralizationCategories } from "optolith-database-schema/types/_I18n" +import { PluralizationCategories, VaryBySystem } from "optolith-database-schema/types/_I18n" import { LocaleMap } from "optolith-database-schema/types/_LocaleMap" const insertParams = (str: string, params: (string | number)[]): string => @@ -25,6 +25,14 @@ export type Translate = ( : [...params: (string | number)[]] ) => string +const isPluralizationCategories = ( + value: string | PluralizationCategories | VaryBySystem, +): value is PluralizationCategories => typeof value === "object" && "other" in value + +const isVaryBySystem = ( + value: string | PluralizationCategories | VaryBySystem, +): value is VaryBySystem => typeof value === "object" && "mac" in value + /** * Creates a translate function based on the given environment, translations and * locales. @@ -34,17 +42,25 @@ export const createTranslate = ( locales: Record, selectedLocale: string | undefined, systemLocale: string, + platform: NodeJS.Platform, + pluralRulesOptions?: Intl.PluralRulesOptions, ) => { const locale = selectedLocale ?? matchSystemLocaleToSupported(Object.keys(locales), systemLocale) - const pluralRules = new Intl.PluralRules(locale) + const pluralRules = new Intl.PluralRules(locale, pluralRulesOptions) const translate: Translate = (key, ...options) => { const value = translations[locale]?.[key] ?? key - if (typeof value === "object" && typeof options[0] === "number") { - const [count] = options - const selectedValue = value[pluralRules.select(count)] ?? value.other - return insertParams(selectedValue, options) + if (isVaryBySystem(value)) { + return platform === "darwin" ? value.mac : platform === "win32" ? value.windows : value.linux + } else if (isPluralizationCategories(value)) { + if (typeof options[0] === "number") { + const [count] = options + const selectedValue = value[pluralRules.select(count)] ?? value.other + return insertParams(selectedValue, options) + } else { + return insertParams(value.other, options) + } } else { const str = typeof value === "string" ? value : key return options.length > 0 ? insertParams(str, options) : str diff --git a/src/updater_window/index.tsx b/src/updater_window/index.tsx index 3e6e4892..44711b45 100644 --- a/src/updater_window/index.tsx +++ b/src/updater_window/index.tsx @@ -19,6 +19,7 @@ ExternalAPI.on("initial-setup", data => { selectedFallbackLocale={globalSettings.fallbackLocale} selectedLocaleEvents={ExternalAPI} systemLocale={systemLocale} + platform={ExternalAPI.platform} locales={locales} ui={translations} >