@@ -18,18 +18,36 @@ const gt = getGettextBuilder()
1818gt.gettext('some string to translate')
1919```
2020 */
21- import GetText from 'node-gettext'
21+ import type { AppTranslations } from './registry.ts'
22+ import { getLanguage , getPlural , translate , translatePlural } from './index.ts'
2223
23- import { getLanguage } from '.'
24+ export interface GettextTranslation {
25+ msgid : string
26+ msgid_plural ?: string
27+ msgstr : string [ ]
28+ }
29+
30+ export interface GettextTranslationContext {
31+ [ msgid : string ] : GettextTranslation
32+ }
33+
34+ export interface GettextTranslationBundle {
35+ headers : {
36+ [ headerName : string ] : string
37+ } ,
38+ translations : {
39+ [ context : string ] : GettextTranslationContext
40+ }
41+ }
2442
2543class GettextBuilder {
2644
27- private locale ?: string
28- private translations = { } as Record < string , unknown >
2945 private debug = false
46+ private language = 'en'
47+ private translations = { } as Record < string , GettextTranslationBundle >
3048
31- setLanguage ( language : string ) : GettextBuilder {
32- this . locale = language
49+ setLanguage ( language : string ) : this {
50+ this . language = language
3351 return this
3452 }
3553
@@ -39,60 +57,56 @@ class GettextBuilder {
3957 *
4058 * @deprecated use `detectLanguage` instead.
4159 */
42- detectLocale ( ) : GettextBuilder {
60+ detectLocale ( ) : this {
4361 return this . detectLanguage ( )
4462 }
4563
4664 /**
4765 * Try to detect locale from context with `en` as fallback value.
4866 * This only works within a Nextcloud page context.
4967 */
50- detectLanguage ( ) : GettextBuilder {
68+ detectLanguage ( ) : this {
5169 return this . setLanguage ( getLanguage ( ) . replace ( '-' , '_' ) )
5270 }
5371
54- addTranslation ( language : string , data : unknown ) : GettextBuilder {
72+ addTranslation ( language : string , data : GettextTranslationBundle ) : this {
5573 this . translations [ language ] = data
5674 return this
5775 }
5876
59- enableDebugMode ( ) : GettextBuilder {
77+ enableDebugMode ( ) : this {
6078 this . debug = true
6179 return this
6280 }
6381
6482 build ( ) : GettextWrapper {
65- return new GettextWrapper ( this . locale || 'en' , this . translations , this . debug )
83+ if ( this . debug ) {
84+ console . debug ( `Creating gettext instance for language ${ this . language } ` )
85+ }
86+
87+ const translations = Object . values ( this . translations [ this . language ] ?. translations [ '' ] ?? { } )
88+ . map ( ( { msgid, msgid_plural : msgidPlural , msgstr } ) => {
89+ if ( msgidPlural !== undefined ) {
90+ return [ `_${ msgid } _::_${ msgidPlural } _` , msgstr ]
91+ }
92+ return [ msgid , msgstr [ 0 ] ]
93+ } )
94+
95+ const bundle : AppTranslations = {
96+ pluralFunction : ( n : number ) => getPlural ( n , this . language ) ,
97+ translations : Object . fromEntries ( translations ) ,
98+ }
99+
100+ return new GettextWrapper ( bundle )
66101 }
67102
68103}
69104
70105class GettextWrapper {
71106
72- private gt : GetText
73-
74- constructor ( locale : string , data : Record < string | symbol | number , unknown > , debug : boolean ) {
75- this . gt = new GetText ( {
76- debug,
77- sourceLocale : 'en' ,
78- } )
79-
80- for ( const key in data ) {
81- this . gt . addTranslations ( key , 'messages' , data [ key ] as object )
82- }
83-
84- this . gt . setLocale ( locale )
85- }
86-
87- private subtitudePlaceholders ( translated : string , vars : Record < string , string | number > ) : string {
88- return translated . replace ( / { ( [ ^ { } ] * ) } / g, ( a , b ) => {
89- const r = vars [ b ]
90- if ( typeof r === 'string' || typeof r === 'number' ) {
91- return r . toString ( )
92- } else {
93- return a
94- }
95- } )
107+ constructor (
108+ private bundle : AppTranslations ,
109+ ) {
96110 }
97111
98112 /**
@@ -102,10 +116,7 @@ class GettextWrapper {
102116 * @param placeholders map of placeholder key to value
103117 */
104118 gettext ( original : string , placeholders : Record < string , string | number > = { } ) : string {
105- return this . subtitudePlaceholders (
106- this . gt . gettext ( original ) ,
107- placeholders ,
108- )
119+ return translate ( '' , original , placeholders , undefined , { bundle : this . bundle } )
109120 }
110121
111122 /**
@@ -117,10 +128,7 @@ class GettextWrapper {
117128 * @param placeholders optional map of placeholder key to value
118129 */
119130 ngettext ( singular : string , plural : string , count : number , placeholders : Record < string , string | number > = { } ) : string {
120- return this . subtitudePlaceholders (
121- this . gt . ngettext ( singular , plural , count ) . replace ( / % n / g, count . toString ( ) ) ,
122- placeholders ,
123- )
131+ return translatePlural ( '' , singular , plural , count , placeholders , { bundle : this . bundle } )
124132 }
125133
126134}
0 commit comments