diff --git a/packages/client/src/i18n.ts b/packages/client/src/i18n.ts index 31e066960..b50cd7290 100644 --- a/packages/client/src/i18n.ts +++ b/packages/client/src/i18n.ts @@ -1,5 +1,43 @@ import { markRaw } from 'vue'; import { locale } from '@/config'; -import { I18n } from '@/scripts/i18n'; + +class I18n> { + // This contains all defined keys, even if a string is missing in a particular language. + // This is achieved by setting English strings as a fallback during locale generation in /locales/index.js + public ts: T; + + constructor(locale: T) { + this.ts = locale; + this.t = this.t.bind(this); + } + + // The key is a string (rather than a Symbol) to allow for the dot-delimited names. + // + // If possible it should probably be preferred to use the locale directly (i.e. the ts member), + // because it may allow for vue to cache information. + // + // Performs string interpolation for patters like `{foo}` and replaces it with the respective value from `args` (using its `toString()` method). + // If a pattern is present in the string but not provided in args, it will not be replaced. + // If `args` is not provided, no interpolation is performed. + public t(key: string, args?: Record): string { + try { + // Resolve dot-delimited names as properties of objects. + let str = key.split('.').reduce((o, i) => o[i], this.ts) as unknown as string; + + // Perform string interpolation. + if (args) { + for (const [k, v] of Object.entries(args)) { + str = str.replace(`{${k}}`, v.toString()); + } + } + + return str; + } catch (err) { + // This should normally not happen because of the English language fallback strings, see comment for ts member. + console.warn(`missing localization '${key}'`); + return key; + } + } +} export const i18n = markRaw(new I18n(locale)); diff --git a/packages/client/src/scripts/i18n.ts b/packages/client/src/scripts/i18n.ts deleted file mode 100644 index 54184386d..000000000 --- a/packages/client/src/scripts/i18n.ts +++ /dev/null @@ -1,29 +0,0 @@ -export class I18n> { - public ts: T; - - constructor(locale: T) { - this.ts = locale; - - //#region BIND - this.t = this.t.bind(this); - //#endregion - } - - // string にしているのは、ドット区切りでのパス指定を許可するため - // なるべくこのメソッド使うよりもlocale直接参照の方がvueのキャッシュ効いてパフォーマンスが良いかも - public t(key: string, args?: Record): string { - try { - let str = key.split('.').reduce((o, i) => o[i], this.ts) as unknown as string; - - if (args) { - for (const [k, v] of Object.entries(args)) { - str = str.replace(`{${k}}`, v.toString()); - } - } - return str; - } catch (err) { - console.warn(`missing localization '${key}'`); - return key; - } - } -}