Skip to content

Commit 965bbf6

Browse files
kabarosdhis2-bot
andauthored
feat: support manifest translations (DHIS2-19443) (backport v42) (#3084)
* fix(translations): sync translations from transifex (master) (#3078) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * fix(translations): sync translations from transifex (master) * chore: support manifest translations (DHIS2-19443) (#3073) * chore: support manifest translations * refactor: update format of manifest translations file --------- Co-authored-by: @dhis2-bot <apps@dhis2.org>
1 parent 763583d commit 965bbf6

34 files changed

Lines changed: 2285 additions & 348 deletions

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"build": "npm test && NODE_ENV=production webpack --progress && npm run manifest",
1818
"postbuild": "cp -r src/i18n icon.png package.json ./build/ && yarn copy-ckeditor",
1919
"validate": "npm ls --depth 0",
20-
"manifest": "d2-manifest package.json build/manifest.webapp",
20+
"manifest": "d2-manifest package.json build/manifest.webapp && node ./scripts/generate-manifest-translations.js",
2121
"lint": "eslint ./src",
2222
"profile": "npm run start -- --profile",
2323
"copy-ckeditor": "mkdir ./build/vendor && cp -r ./node_modules/ckeditor ./build/vendor",
@@ -69,6 +69,7 @@
6969
"node-sass": "npm:sass@^1.58.0",
7070
"precommit-hook": "^3.0.0",
7171
"prettier": "^1.13.7",
72+
"properties-file": "^3.5.12",
7273
"recompose": "^0.23.1",
7374
"redux-logger": "^3.0.6",
7475
"sass-loader": "^6.0.5",
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* This is a script used as part of the build process to generate manifest translations
3+
*
4+
* This script is specific to the maintenance app - other apps that use the platform tools have this support
5+
* through @dhis2/cli-app-scripts (and i18next under the hood) - so this script adapts to the specifics of the maintenance app
6+
* in order to support translations for shortcuts.
7+
*
8+
* In general, it performs three steps:
9+
*
10+
* 1. It reads the i18n_module_en.properties which is the source of truth for translation keys (not "en.pot")
11+
* 2. It looks for keys that start with MANIFEST_ prefix (this is an internal convention)
12+
* 3. It generates manifest.webapp.translations.json file in the format expected by the backend
13+
*
14+
*/
15+
const { readFileSync, readdirSync, writeFileSync } = require('node:fs');
16+
const { getProperties } = require('properties-file');
17+
18+
try {
19+
const SOURCE_DIR = 'src/i18n';
20+
21+
console.debug('---- generating manifest translations');
22+
23+
// i18n_module_en.properties is our template file (equivalent to .pot)
24+
// we use it to find the manifest keys that should be translated
25+
const keyToMatch = /^MANIFEST_/;
26+
const baseLanguageProperties = getProperties(readFileSync(`${SOURCE_DIR}/i18n_module_en.properties`))
27+
const shortcutKeys = Object.keys(
28+
baseLanguageProperties
29+
).filter(key => {
30+
return keyToMatch.exec(key);
31+
});
32+
console.debug(`${shortcutKeys.length} keys with MANIFEST_ prefix found.`);
33+
34+
// Finding all the .properties file for all languages
35+
const propsFiles = readdirSync(SOURCE_DIR).filter(fn =>
36+
fn.endsWith('.properties')
37+
);
38+
39+
console.debug(`${propsFiles.length} .properties files found.`);
40+
41+
const keyMap = {
42+
"APP_TITLE": "title",
43+
"APP_DESCRIPTION": "description"
44+
}
45+
const result = propsFiles.map(file => {
46+
// read the properties file using getProperties library
47+
const properties = getProperties(readFileSync('src/i18n/' + file));
48+
const locale = file
49+
.replace(/^i18n_module_/, '')
50+
.replace('.properties', '');
51+
const foundTranslations = Object.entries(properties).filter(
52+
([key, value]) => {
53+
return shortcutKeys.includes(key);
54+
}
55+
);
56+
// change the translations to the format expected by the backend
57+
const translations = foundTranslations.reduce((prev, curr) => {
58+
const [key, value] = curr
59+
60+
// For shortcuts, the key should be in the format of SHORTCUT_NAME_VALUE where NAME_VALUE is the "name" property for a shortcut in d2.config or manifest.webapp
61+
// the java .properties file do not use spaces for the keys (unlike pot files) so we're getting that value manually here instead of relying on the key as we do in app-platform
62+
let keyToUse = baseLanguageProperties[key]
63+
64+
let cleaned_key = key?.replace(/MANIFEST_/, '')
65+
66+
if(cleaned_key.startsWith('SHORTCUT')) {
67+
prev.shortcuts[keyToUse] = value
68+
} else if (cleaned_key.startsWith('APP')) {
69+
prev[keyMap[cleaned_key]] = value
70+
}
71+
72+
return prev;
73+
}, {shortcuts: {}});
74+
75+
return {
76+
locale,
77+
...translations,
78+
};
79+
});
80+
81+
writeFileSync(
82+
'./build/manifest.webapp.translations.json',
83+
JSON.stringify(result, null, 2)
84+
);
85+
console.log(
86+
`---- generated "./build/manifest.webapp.translations.json" file`
87+
);
88+
} catch (err) {
89+
console.error('Generating the manifest.webapp translations failed.');
90+
console.error(err);
91+
}

src/i18n/i18n_module_ar.properties

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,3 +2396,54 @@ ownership=Ownership
23962396
validation_result=\u0646\u062a\u064a\u062c\u0629 \u0627\u0644\u062a\u062d\u0642\u0642
23972397
sql=SQL
23982398
categories_cannot_be_empty=Categories cannot be empty
2399+
2400+
# Translations for shortcuts and app title in the manifest file
2401+
MANIFEST_APP_TITLE=\u062a\u0637\u0628\u064a\u0642 \u0627\u0644\u0635\u064a\u0627\u0646\u0629
2402+
MANIFEST_APP_DESCRIPTION=DHIS2 Maintenance app
2403+
MANIFEST_SHORTCUT_Categories=\u0627\u0644\u0641\u0626\u0627\u062a
2404+
MANIFEST_SHORTCUT_Category_options=\u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u0641\u0626\u0629
2405+
MANIFEST_SHORTCUT_Category_combinations=Category combinations
2406+
MANIFEST_SHORTCUT_Category_option_combinations=Category option combinations
2407+
MANIFEST_SHORTCUT_Category_option_groups=Category option groups
2408+
MANIFEST_SHORTCUT_Category_option_group_sets=Category option group sets
2409+
MANIFEST_SHORTCUT_Data_elements=\u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2410+
MANIFEST_SHORTCUT_Data_element_groups_=\u0645\u062c\u0645\u0648\u0639\u0627\u062a \u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2411+
MANIFEST_SHORTCUT_Data_element_group_sets=Data element group sets
2412+
MANIFEST_SHORTCUT_Data_sets=\u062d\u0632\u0645 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2413+
MANIFEST_SHORTCUT_Data_set_notifications=\u0625\u0634\u0639\u0627\u0631\u0627\u062a \u062d\u0632\u0645\u0629 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2414+
MANIFEST_SHORTCUT_Indicators=\u0627\u0644\u0645\u0624\u0634\u0631\u0627\u062a
2415+
MANIFEST_SHORTCUT_Indicator_types=\u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0645\u0624\u0634\u0631\u0627\u062a
2416+
MANIFEST_SHORTCUT_Indicator_groups=\u0645\u062c\u0645\u0648\u0639\u0627\u062a \u0627\u0644\u0645\u0624\u0634\u0631\u0627\u062a
2417+
MANIFEST_SHORTCUT_Indicator_group_sets=Indicator group sets
2418+
MANIFEST_SHORTCUT_Program_indicators=\u0645\u0624\u0634\u0631\u0627\u062a \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c
2419+
MANIFEST_SHORTCUT_Program_indicator_groups=Program indicator groups
2420+
MANIFEST_SHORTCUT_Organisation_units=\u0627\u0644\u0648\u062d\u062f\u0627\u062a \u0627\u0644\u062a\u0646\u0638\u064a\u0645\u064a\u0629
2421+
MANIFEST_SHORTCUT_Organisaiton_unit_groups=Organisaiton unit groups
2422+
MANIFEST_SHORTCUT_Organisation_unit_group_sets=Organisation unit group sets
2423+
MANIFEST_SHORTCUT_Organisation_unit_levels=\u0645\u0633\u062a\u0648\u064a\u0627\u062a \u0627\u0644\u0648\u062d\u062f\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645\u064a\u0629
2424+
MANIFEST_SHORTCUT_Hierarchy_operations=\u0639\u0645\u0644\u064a\u0627\u062a \u0627\u0644\u062a\u0633\u0644\u0633\u0644 \u0627\u0644\u0647\u0631\u0645\u064a
2425+
MANIFEST_SHORTCUT_Programs=\u0627\u0644\u0628\u0631\u0627\u0645\u062c
2426+
MANIFEST_SHORTCUT_Tracked_entity_attributes=Tracked entity attributes
2427+
MANIFEST_SHORTCUT_Relationship_types=\u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0639\u0644\u0627\u0642\u0627\u062a
2428+
MANIFEST_SHORTCUT_Tracked_entity_types=\u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0643\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0645\u062a\u0639\u0642\u0628\u0629
2429+
MANIFEST_SHORTCUT_Program_rules=Program rules
2430+
MANIFEST_SHORTCUT_Program_rule_variables=Program rule variables
2431+
MANIFEST_SHORTCUT_Validation_rules=\u0642\u0648\u0627\u0639\u062f \u0627\u0644\u062a\u062d\u0642\u0642
2432+
MANIFEST_SHORTCUT_Validation_rule_groups=Validation rule groups
2433+
MANIFEST_SHORTCUT_Validation_notifications=Validation notifications
2434+
MANIFEST_SHORTCUT_Constants=\u0627\u0644\u062b\u0648\u0627\u0628\u062a
2435+
MANIFEST_SHORTCUT_Attributes=\u0627\u0644\u0633\u0645\u0627\u062a
2436+
MANIFEST_SHORTCUT_Option_sets=Option sets
2437+
MANIFEST_SHORTCUT_Option_groups=Option groups
2438+
MANIFEST_SHORTCUT_Option_group_sets=Option group sets
2439+
MANIFEST_SHORTCUT_Legends=\u0645\u0641\u0627\u062a\u064a\u062d \u0625\u064a\u0636\u0627\u062d\u064a\u0629
2440+
MANIFEST_SHORTCUT_Predictors=Predictors
2441+
MANIFEST_SHORTCUT_Predictor_groups=Predictor groups
2442+
MANIFEST_SHORTCUT_Push_analysis=\u062a\u062d\u0644\u064a\u0644 \u0627\u0644\u062f\u0641\u0639
2443+
MANIFEST_SHORTCUT_External_map_layers=\u0637\u0628\u0642\u0627\u062a \u062e\u0631\u064a\u0637\u0629 \u062e\u0627\u0631\u062c\u064a\u0629
2444+
MANIFEST_SHORTCUT_Data_approval_levels=\u0645\u0633\u062a\u0648\u064a\u0627\u062a \u0627\u0644\u0645\u0648\u0627\u0641\u0642\u0629 \u0639\u0644\u0649 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2445+
MANIFEST_SHORTCUT_Data_approval_workflows=\u0633\u064a\u0631 \u0639\u0645\u0644 \u0627\u0644\u0645\u0648\u0627\u0641\u0642\u0629 \u0639\u0644\u0649 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2446+
MANIFEST_SHORTCUT_Locales=\u0644\u063a\u0627\u062a
2447+
MANIFEST_SHORTCUT_SQL_views=SQL views
2448+
MANIFEST_SHORTCUT_Icons=Icons
2449+
MANIFEST_SHORTCUT_Analytics_table_hooks=Analytics table hooks

src/i18n/i18n_module_ar_IQ.properties

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,7 @@ failed_to_save_organisation_unit=Failed to save organisation unit
20822082
last_average_org_unit=\u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0623\u062e\u064a\u0631\u0629 (\u0627\u0644\u0645\u062a\u0648\u0633\u0637 \u0641\u064a \u0627\u0644\u062a\u0633\u0644\u0633\u0644 \u0627\u0644\u0647\u0631\u0645\u064a \u0644\u0644\u0648\u062d\u062f\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645\u064a\u0629)
20832083
last=Last value (sum in org unit hierarchy)
20842084
first=First value (sum in org unit hierarchy)
2085-
first_average_org_unit=First value (averge in org unit hierarchy)
2085+
first_average_org_unit=First value (average in org unit hierarchy)
20862086
last_in_period=Last value in period (sum in org unit hierarchy)
20872087
last_in_period_average_org_unit=Last value in period (average in org unit hierarchy)
20882088
last_last_org_unit=Last value in period (last value in org unit hierarchy)
@@ -2377,17 +2377,17 @@ skip_in_analytics=Skip in analytics
23772377
analytics_table_hook=Analytics table hooks
23782378
intro_analytics_table_hook=Configure hooks in SQL that run during the analytics process
23792379
analytics_table_hook_management=Analytics table hooks management
2380-
phase=Phase that the SQL script should be invoked
2381-
resource_table_populated=After the temporary resource tables have been populated
2382-
analytics_table_populated=After the temporary analytics tables have been populated
2383-
resource_table_type=Resource table
2380+
phase=After population of which temporary tables should the SQL script be invoked?
2381+
resource_table_populated=Resource tables
2382+
analytics_table_populated=Analytics tables
2383+
resource_table_type=Which resource table
23842384
org_unit_structure=Organisation unit structure
23852385
data_set_org_unit_category=Data set organisation unit category
23862386
category_option_combo_name=Category option combo name
23872387
org_unit_group_set_structure=Organisation unit group set structure
23882388
data_approval_remap_level=Data approval remap level
23892389
data_approval_min_level=Data approval minimum level
2390-
analytics_table_type=Analytics table
2390+
analytics_table_type=Which analytics table
23912391
data_value=Data value
23922392
completeness=Completeness
23932393
completeness_target=Completeness target
@@ -2396,3 +2396,54 @@ ownership=Ownership
23962396
validation_result=Validation result
23972397
sql=SQL
23982398
categories_cannot_be_empty=Categories cannot be empty
2399+
2400+
# Translations for shortcuts and app title in the manifest file
2401+
MANIFEST_APP_TITLE=Maintenance app
2402+
MANIFEST_APP_DESCRIPTION=DHIS2 Maintenance app
2403+
MANIFEST_SHORTCUT_Categories=\u0627\u0644\u0641\u0626\u0627\u062a
2404+
MANIFEST_SHORTCUT_Category_options=Category options
2405+
MANIFEST_SHORTCUT_Category_combinations=Category combinations
2406+
MANIFEST_SHORTCUT_Category_option_combinations=Category option combinations
2407+
MANIFEST_SHORTCUT_Category_option_groups=Category option groups
2408+
MANIFEST_SHORTCUT_Category_option_group_sets=Category option group sets
2409+
MANIFEST_SHORTCUT_Data_elements=\u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2410+
MANIFEST_SHORTCUT_Data_element_groups_=Data element groups
2411+
MANIFEST_SHORTCUT_Data_element_group_sets=Data element group sets
2412+
MANIFEST_SHORTCUT_Data_sets=\u062d\u0632\u0645 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
2413+
MANIFEST_SHORTCUT_Data_set_notifications=Data set notifications
2414+
MANIFEST_SHORTCUT_Indicators=\u0627\u0644\u0645\u0624\u0634\u0631\u0627\u062a
2415+
MANIFEST_SHORTCUT_Indicator_types=Indicator types
2416+
MANIFEST_SHORTCUT_Indicator_groups=Indicator groups
2417+
MANIFEST_SHORTCUT_Indicator_group_sets=Indicator group sets
2418+
MANIFEST_SHORTCUT_Program_indicators=Program indicators
2419+
MANIFEST_SHORTCUT_Program_indicator_groups=Program indicator groups
2420+
MANIFEST_SHORTCUT_Organisation_units=\u0627\u0644\u0648\u062d\u062f\u0627\u062a \u0627\u0644\u062a\u0646\u0638\u064a\u0645\u064a\u0629
2421+
MANIFEST_SHORTCUT_Organisaiton_unit_groups=Organisaiton unit groups
2422+
MANIFEST_SHORTCUT_Organisation_unit_group_sets=Organisation unit group sets
2423+
MANIFEST_SHORTCUT_Organisation_unit_levels=Organisation unit levels
2424+
MANIFEST_SHORTCUT_Hierarchy_operations=Hierarchy operations
2425+
MANIFEST_SHORTCUT_Programs=Programs
2426+
MANIFEST_SHORTCUT_Tracked_entity_attributes=Tracked entity attributes
2427+
MANIFEST_SHORTCUT_Relationship_types=Relationship types
2428+
MANIFEST_SHORTCUT_Tracked_entity_types=Tracked entity types
2429+
MANIFEST_SHORTCUT_Program_rules=Program rules
2430+
MANIFEST_SHORTCUT_Program_rule_variables=Program rule variables
2431+
MANIFEST_SHORTCUT_Validation_rules=Validation rules
2432+
MANIFEST_SHORTCUT_Validation_rule_groups=Validation rule groups
2433+
MANIFEST_SHORTCUT_Validation_notifications=Validation notifications
2434+
MANIFEST_SHORTCUT_Constants=Constants
2435+
MANIFEST_SHORTCUT_Attributes=Attributes
2436+
MANIFEST_SHORTCUT_Option_sets=Option sets
2437+
MANIFEST_SHORTCUT_Option_groups=Option groups
2438+
MANIFEST_SHORTCUT_Option_group_sets=Option group sets
2439+
MANIFEST_SHORTCUT_Legends=Legends
2440+
MANIFEST_SHORTCUT_Predictors=Predictors
2441+
MANIFEST_SHORTCUT_Predictor_groups=Predictor groups
2442+
MANIFEST_SHORTCUT_Push_analysis=Push analysis
2443+
MANIFEST_SHORTCUT_External_map_layers=External map layers
2444+
MANIFEST_SHORTCUT_Data_approval_levels=Data approval levels
2445+
MANIFEST_SHORTCUT_Data_approval_workflows=Data approval workflows
2446+
MANIFEST_SHORTCUT_Locales=Locales
2447+
MANIFEST_SHORTCUT_SQL_views=SQL views
2448+
MANIFEST_SHORTCUT_Icons=Icons
2449+
MANIFEST_SHORTCUT_Analytics_table_hooks=Analytics table hooks

0 commit comments

Comments
 (0)