@@ -8,7 +8,7 @@ import YAML from 'js-yaml';
88import marky from 'marky' ;
99import { createRequire } from 'module' ;
1010import { compile , toSafeIdentifier } from 'json-schema-to-typescript-lite' ;
11-
11+ import { isReference , dereferencedTranslatableContent , dereferenceUntranslatedContent } from './references.js' ;
1212import fetchTranslations , { expandTStrings , sortObject } from './translations.js' ;
1313
1414const require = createRequire ( import . meta. url ) ;
@@ -117,16 +117,20 @@ function processData(options, type) {
117117 let categories = generateCategories ( dataDir , tstrings ) ;
118118 if ( options . processCategories ) options . processCategories ( categories ) ;
119119
120- let fields = generateFields ( dataDir , tstrings , searchableFieldIDs ) ;
120+ /** @type {References } */
121+ const references = { fields : { } , presets : { } } ;
122+ let fields = generateFields ( dataDir , tstrings , searchableFieldIDs , references ) ;
121123 if ( options . processFields ) options . processFields ( fields ) ;
122124
123- let presets = generatePresets ( dataDir , tstrings , searchableFieldIDs , options . listReusedIcons ) ;
125+ let presets = generatePresets ( dataDir , tstrings , searchableFieldIDs , options . listReusedIcons , references ) ;
124126 if ( options . processPresets ) options . processPresets ( presets ) ;
125127
126128 // Additional consistency checks
127129 validateCategoryPresets ( categories , presets ) ;
128130 validatePresetFields ( presets , fields ) ;
129131
132+ dereferenceUntranslatedContent ( presets , fields ) ;
133+
130134 const defaults = read ( dataDir + '/preset_defaults.json' ) ;
131135 if ( defaults ) {
132136 validateSchema ( dataDir + '/preset_defaults.json' , defaults , defaultsSchema ) ;
@@ -150,6 +154,8 @@ function processData(options, type) {
150154 let icons = generateIconsList ( presets , fields , categories ) ;
151155 fs . writeFileSync ( interimDir + '/icons.json' , JSON . stringify ( icons , null , 4 ) ) ;
152156
157+ dereferencedTranslatableContent ( tstrings , references , true ) ;
158+
153159 if ( type !== 'build-dist' ) return ;
154160
155161 const doFetchTranslations = options . translOrgId && options . translProjectId ;
@@ -198,7 +204,7 @@ function processData(options, type) {
198204 ] ;
199205
200206 if ( doFetchTranslations ) {
201- tasks . push ( fetchTranslations ( options ) ) ;
207+ tasks . push ( fetchTranslations ( options , references ) ) ;
202208 }
203209 return Promise . all ( tasks ) ;
204210}
@@ -247,7 +253,7 @@ function generateCategories(dataDir, tstrings) {
247253}
248254
249255
250- function generateFields ( dataDir , tstrings , searchableFieldIDs ) {
256+ function generateFields ( dataDir , tstrings , searchableFieldIDs , references ) {
251257 let fields = { } ;
252258
253259 fs . globSync ( dataDir + '/fields/**/*.json' , {
@@ -262,10 +268,13 @@ function generateFields(dataDir, tstrings, searchableFieldIDs) {
262268
263269 const label = field . label ;
264270
265- if ( ! label . startsWith ( '{' ) ) {
271+ if ( isReference ( label ) ) {
272+ references . fields [ id ] ||= { } ;
273+ references . fields [ id ] . labelAndTerms = label ;
274+ } else {
266275 t . label = label ;
267- delete field . label ;
268276 }
277+ delete field . label ;
269278
270279 validateTerms ( field . terms , `field "${ id } "` ) ;
271280 tstrings . fields [ id ] . terms = Array . from ( new Set (
@@ -279,21 +288,42 @@ function generateFields(dataDir, tstrings, searchableFieldIDs) {
279288 searchableFieldIDs [ id ] = true ;
280289 }
281290
282- if ( field . placeholder && ! field . placeholder . startsWith ( '{' ) ) {
283- t . placeholder = field . placeholder ;
291+ if ( field . placeholder ) {
292+ if ( isReference ( field . placeholder ) ) {
293+ references . fields [ id ] ||= { } ;
294+ references . fields [ id ] . placeholder = field . placeholder ;
295+ } else {
296+ t . placeholder = field . placeholder ;
297+ }
284298 delete field . placeholder ;
285299 }
286300
287301 if ( field . strings ) {
288- for ( let key in field . strings ) {
289- t [ key ] = field . strings [ key ] ;
302+ for ( let prop in field . strings ) {
303+ t [ prop ] = { } ;
304+ for ( const [ key , value ] of Object . entries ( field . strings [ prop ] ) ) {
305+ if ( typeof value === 'string' && isReference ( value ) ) {
306+ references . fields [ id ] ||= { } ;
307+ references . fields [ id ] . options ||= { } ;
308+ references . fields [ id ] . options [ prop ] ||= { } ;
309+ references . fields [ id ] . options [ prop ] [ key ] = value ;
310+ } else {
311+ t [ prop ] [ key ] = value ;
312+ }
313+ }
290314 }
291315 if ( ! field . options && field . strings . options ) {
292316 field . options = Object . keys ( field . strings . options ) ;
293317 }
294318 delete field . strings ;
295319 }
296320
321+ if ( field . stringsCrossReference ) {
322+ references . fields [ id ] ||= { } ;
323+ references . fields [ id ] . stringsCrossReference = field . stringsCrossReference ;
324+ delete field . stringsCrossReference ;
325+ }
326+
297327 fields [ id ] = field ;
298328 } ) ;
299329
@@ -308,7 +338,7 @@ function stripLeadingUnderscores(str) {
308338}
309339
310340
311- function generatePresets ( dataDir , tstrings , searchableFieldIDs , listReusedIcons ) {
341+ function generatePresets ( dataDir , tstrings , searchableFieldIDs , listReusedIcons , references ) {
312342 let presets = { } ;
313343
314344 let icons = { } ;
@@ -330,11 +360,12 @@ function generatePresets(dataDir, tstrings, searchableFieldIDs, listReusedIcons)
330360 let names = new Set ( [ ] ) ;
331361 tstrings . presets [ id ] = { } ;
332362
333- if ( ! preset . name . startsWith ( '{' ) ) {
363+ if ( isReference ( preset . name ) ) {
364+ references . presets [ id ] ||= { } ;
365+ references . presets [ id ] . nameTermsAliases = preset . name ;
366+ } else {
334367 tstrings . presets [ id ] . name = preset . name ;
335368 names . add ( preset . name . toLowerCase ( ) ) ;
336- // don't include localized strings in the presets dist file since they're already in the locale file
337- delete preset . name ;
338369 }
339370
340371 preset . aliases = Array . from ( new Set (
@@ -359,6 +390,8 @@ function generatePresets(dataDir, tstrings, searchableFieldIDs, listReusedIcons)
359390 // don't include localized strings in the presets dist file since they're already in the locale file
360391 delete preset . aliases ;
361392 delete preset . terms ;
393+ delete preset . name ;
394+
362395
363396 if ( preset . moreFields ) {
364397 preset . moreFields . forEach ( fieldID => { searchableFieldIDs [ fieldID ] = true ; } ) ;
@@ -424,13 +457,6 @@ function generateTranslations(fields, presets, tstrings, searchableFieldIDs) {
424457 yamlField [ '#label' ] = `${ field . key } =*` ;
425458 }
426459 optkeys . forEach ( k => {
427- if ( typeof options [ k ] === 'string' && options [ k ] . startsWith ( '{' ) ) {
428- // skip, this references another field or preset, so we don't want
429- // translators to translate it.
430- delete options [ k ] ;
431- return ;
432- }
433-
434460 if ( typeof options [ k ] === 'string' ) {
435461 options [ '#' + k ] = field . key ? `${ field . key } =${ k } ` : `field "${ fieldId } " with value "${ k } "` ;
436462 } else {
@@ -562,7 +588,7 @@ function generateTaginfo(presets, fields, deprecated, discarded, tstrings, proje
562588
563589
564590 let name = tstrings . presets [ id ] . name ;
565- if ( ! name && preset . name . startsWith ( '{' ) ) {
591+ if ( ! name && isReference ( preset . name ) ) {
566592 name = tstrings . presets [ preset . name . slice ( 1 , - 1 ) ] . name ;
567593 }
568594 let legacy = ( preset . searchable === false ) ? ' (unsearchable)' : '' ;
@@ -609,7 +635,7 @@ function generateTaginfo(presets, fields, deprecated, discarded, tstrings, proje
609635 let tag = { key : key } ;
610636
611637 let label = tstrings . fields [ id ] . label ;
612- if ( ! label && field . label . startsWith ( '{' ) ) {
638+ if ( ! label && field . label && isReference ( field . label ) ) {
613639 label = tstrings . fields [ field . label . slice ( 1 , - 1 ) ] . label ;
614640 }
615641 tag . description = [ `🄵 ${ label } ` ] ;
@@ -627,18 +653,8 @@ function generateTaginfo(presets, fields, deprecated, discarded, tstrings, proje
627653 tag = { key : key , value : value } ;
628654 }
629655 let valueLabel = tstrings . fields [ id ] . options ?. [ value ] ;
630- if ( ! valueLabel && field . stringsCrossReference ) {
631- valueLabel = tstrings . fields [ field . stringsCrossReference . slice ( 1 , - 1 ) ] . options ?. [ value ] ;
632- }
633- if ( valueLabel && typeof valueLabel === 'string' ) {
634- const match = valueLabel . match ( / ^ \{ ( .* ) \} $ / ) ?. [ 1 ] ;
635- if ( match ) {
636- const [ group , ...remainder ] = match . split ( '/' ) ;
637- const reference = tstrings [ group ] [ remainder . join ( '/' ) ] ;
638- if ( ! reference ) throw new Error ( `${ valueLabel } is not a valid reference` ) ;
639656
640- valueLabel = reference . name || reference . label ;
641- }
657+ if ( valueLabel && typeof valueLabel === 'string' ) {
642658 tag . description = [ `🄵🅅 ${ label } : ${ valueLabel } ` ] ;
643659 } else {
644660 tag . description = [ `🄵🅅 ${ label } : \`${ value } \`` ] ;
0 commit comments