import React from "react" ; import { observable } from "mobx" ; import { createStorageHelper } from "./extension/storage" ; import { getURL } from "./extension" ; import { createLogger } from "./utils" ; export type Locale = "en" | "de" | "ru" | "sr" | "zh_TW" ; export const supportedLocales = { en : "English" , de : "German" , ru : "Russian" , sr : "Serbian" , zh_TW : "Chinese (Taiwan)" , } ; export interface Messages { [ key ] : { message : string ; } ; } export const logger = createLogger ( { systemPrefix : "[I18n]" } ) ; export const messages = observable . map < Locale , Messages > ( { } , { deep : false } ) ; const storage = createStorageHelper ( "i18n" , { area : "sync" , autoLoad : true , defaultValue : { lang : getSystemLocale ( ) , } , } ) ; async function loadMessages ( lang ) { if ( messages . has ( lang ) || ! supportedLocales [ lang ] ) { return ; } try { const localizationFile = getURL ( `_locales/${ lang }/messages.json` ) ; const data = await fetch ( localizationFile ) . then ( res => res . json ( ) ) ; messages . set ( lang , data ) ; } catch ( error ) { logger . error ( `loading locale "${ lang }" has failed` , error ) ; } } export function getMessage ( key ) ; export function getMessage ( key , placeholders ) ; export function getMessage ( key , placeholders ? ) { const message = messages . get ( getLocale ( ) ) ?. [ key ] ?. message || messages . get ( "en" ) ?. [ key ] ?. message ; if ( ! message ) { return `[${ key }]` ; } if ( placeholders ) { const chunks = message . split ( /%(.*?)%/ ) . map ( chunk => placeholders [ chunk ] ?? chunk ) ; if ( chunks . some ( React . isValidElement ) ) { return React . Children . toArray ( chunks ) ; } else { return chunks . join ( "" ) ; } } return message ; } export async function setLocale ( lang ) { await loadMessages ( lang ) ; storage . merge ( { lang } ) ; } export function getLocale ( ) { return storage . get ( ) . lang ; } export function getSystemLocale ( ) { const locale = chrome . i18n . getUILanguage ( ) as Locale ; if ( supportedLocales [ locale ] ) return locale ; const lang = locale . split ( /_-/ ) [ 0 ] as Locale ; return supportedLocales [ lang ] ? lang : "en" ; } export async function i18nInit ( ) { await storage . whenReady ; await loadMessages ( "en" ) ; await loadMessages ( getLocale ( ) ) ; }