@@ -21,7 +21,10 @@ import counterpart from "counterpart";
2121import React from "react" ;
2222import { logger } from "matrix-js-sdk/src/logger" ;
2323import { Optional } from "matrix-events-sdk" ;
24- import { MapWithDefault , safeSet } from "matrix-js-sdk/src/utils" ;
24+ import { MapWithDefault } from "matrix-js-sdk/src/utils" ;
25+ import { normalizeLanguageKey , TranslationKey as _TranslationKey , KEY_SEPARATOR } from "matrix-web-i18n" ;
26+ import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api" ;
27+ import _ from "lodash" ;
2528
2629import type Translations from "./i18n/strings/en_EN.json" ;
2730import SettingsStore from "./settings/SettingsStore" ;
@@ -30,19 +33,20 @@ import { SettingLevel } from "./settings/SettingLevel";
3033import { retry } from "./utils/promise" ;
3134import SdkConfig from "./SdkConfig" ;
3235import { ModuleRunner } from "./modules/ModuleRunner" ;
33- import { Leaves } from "./@types/common" ;
3436
3537// @ts -ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
3638import webpackLangJsonUrl from "$webapp/i18n/languages.json" ;
3739
40+ export { normalizeLanguageKey , getNormalizedLanguageKeys } from "matrix-web-i18n" ;
41+
3842const i18nFolder = "i18n/" ;
3943
4044// Control whether to also return original, untranslated strings
4145// Useful for debugging and testing
4246const ANNOTATE_STRINGS = false ;
4347
4448// We use english strings as keys, some of which contain full stops
45- counterpart . setSeparator ( "|" ) ;
49+ counterpart . setSeparator ( KEY_SEPARATOR ) ;
4650
4751// see `translateWithFallback` for an explanation of fallback handling
4852const FALLBACK_LOCALE = "en" ;
@@ -110,7 +114,7 @@ export function getUserLanguage(): string {
110114 * }
111115 * }
112116 */
113- export type TranslationKey = Leaves < typeof Translations , "|" , string | { other : string } , 4 > ;
117+ export type TranslationKey = _TranslationKey < typeof Translations > ;
114118
115119// Function which only purpose is to mark that a string is translatable
116120// Does not actually do anything. It's helpful for automatic extraction of translatable strings
@@ -541,41 +545,6 @@ export function getLanguageFromBrowser(): string {
541545 return getLanguagesFromBrowser ( ) [ 0 ] ;
542546}
543547
544- /**
545- * Turns a language string, normalises it,
546- * (see normalizeLanguageKey) into an array of language strings
547- * with fallback to generic languages
548- * (eg. 'pt-BR' => ['pt-br', 'pt'])
549- *
550- * @param {string } language The input language string
551- * @return {string[] } List of normalised languages
552- */
553- export function getNormalizedLanguageKeys ( language : string ) : string [ ] {
554- const languageKeys : string [ ] = [ ] ;
555- const normalizedLanguage = normalizeLanguageKey ( language ) ;
556- const languageParts = normalizedLanguage . split ( "-" ) ;
557- if ( languageParts . length === 2 && languageParts [ 0 ] === languageParts [ 1 ] ) {
558- languageKeys . push ( languageParts [ 0 ] ) ;
559- } else {
560- languageKeys . push ( normalizedLanguage ) ;
561- if ( languageParts . length === 2 ) {
562- languageKeys . push ( languageParts [ 0 ] ) ;
563- }
564- }
565- return languageKeys ;
566- }
567-
568- /**
569- * Returns a language string with underscores replaced with
570- * hyphens, and lowercased.
571- *
572- * @param {string } language The language string to be normalized
573- * @returns {string } The normalized language string
574- */
575- export function normalizeLanguageKey ( language : string ) : string {
576- return language . toLowerCase ( ) . replace ( "_" , "-" ) ;
577- }
578-
579548export function getCurrentLanguage ( ) : string {
580549 return counterpart . getLocale ( ) ;
581550}
@@ -662,34 +631,26 @@ async function getLanguage(langPath: string): Promise<ICounterpartTranslation> {
662631 return res . json ( ) ;
663632}
664633
665- export interface ICustomTranslations {
666- // Format is a map of english string to language to override
667- [ str : string ] : {
668- [ lang : string ] : string ;
669- } ;
670- }
671-
672- let cachedCustomTranslations : Optional < ICustomTranslations > = null ;
634+ let cachedCustomTranslations : Optional < TranslationStringsObject > = null ;
673635let cachedCustomTranslationsExpire = 0 ; // zero to trigger expiration right away
674636
675637// This awkward class exists so the test runner can get at the function. It is
676638// not intended for practical or realistic usage.
677639export class CustomTranslationOptions {
678- public static lookupFn ?: ( url : string ) => ICustomTranslations ;
640+ public static lookupFn ?: ( url : string ) => TranslationStringsObject ;
679641
680642 private constructor ( ) {
681643 // static access for tests only
682644 }
683645}
684646
685- function doRegisterTranslations ( customTranslations : ICustomTranslations ) : void {
686- // We convert the operator-friendly version into something counterpart can
687- // consume.
647+ function doRegisterTranslations ( customTranslations : TranslationStringsObject ) : void {
648+ // We convert the operator-friendly version into something counterpart can consume.
688649 // Map: lang → Record: string → translation
689650 const langs : MapWithDefault < string , Record < string , string > > = new MapWithDefault ( ( ) => ( { } ) ) ;
690- for ( const [ str , translations ] of Object . entries ( customTranslations ) ) {
691- for ( const [ lang , newStr ] of Object . entries ( translations ) ) {
692- safeSet ( langs . getOrCreate ( lang ) , str , newStr ) ;
651+ for ( const [ translationKey , translations ] of Object . entries ( customTranslations ) ) {
652+ for ( const [ lang , translation ] of Object . entries ( translations ) ) {
653+ _ . set ( langs . getOrCreate ( lang ) , translationKey . split ( KEY_SEPARATOR ) , translation ) ;
693654 }
694655 }
695656
@@ -719,11 +680,11 @@ export async function registerCustomTranslations({
719680 if ( ! lookupUrl ) return ; // easy - nothing to do
720681
721682 try {
722- let json : Optional < ICustomTranslations > ;
683+ let json : Optional < TranslationStringsObject > ;
723684 if ( testOnlyIgnoreCustomTranslationsCache || Date . now ( ) >= cachedCustomTranslationsExpire ) {
724685 json = CustomTranslationOptions . lookupFn
725686 ? CustomTranslationOptions . lookupFn ( lookupUrl )
726- : ( ( await ( await fetch ( lookupUrl ) ) . json ( ) ) as ICustomTranslations ) ;
687+ : ( ( await ( await fetch ( lookupUrl ) ) . json ( ) ) as TranslationStringsObject ) ;
727688 cachedCustomTranslations = json ;
728689
729690 // Set expiration to the future, but not too far. Just trying to avoid
0 commit comments