#!/bin/python3
import argparse
import json
import os
import sys
# This allows for importing from the localization and util directories NOTE: Auto importing tools will also prepend the import paths with "tools." this will not work and needs to be removed from import paths
sys . path . append ( os . path . abspath ( os . path . join ( os . path . dirname ( __file__ ) , " .. " ) ) )
from util . time import ExecutionTimer ;
timer = ExecutionTimer ( )
from dynamicVariables import (
extractVariablesFromDict ,
identifyLocaleDynamicVariableDifferences ,
prettyPrintIssuesTable ,
identifyAndPrintOldDynamicVariables , extractFormattingTags ,
)
from localization . localeTypes import generateLocalesType
from util . logger import console
from util . fileUtils import createMappedJsonFileDictionary , writeFile
# These string keys are ignored for formatting tag checks
ignored_strings_formatting = {
" pl " : [
# disappearingMessagesTurnedOffYouGroup in pl only has one bold word as the word combines both bold words
" disappearingMessagesTurnedOffYouGroup " ] ,
" ru " : [
# disappearingMessagesTurnedOffGroup in ru only has one bold word as the word combines both bold words
" disappearingMessagesTurnedOffGroup " ] ,
" sr_CS " : [
# disappearingMessagesTurnedOffGroup in sr_CS only has one bold word as the word combines both bold words
" disappearingMessagesTurnedOffGroup " ]
}
# If the --throw-error-on-missing flag is passed, the script will exit with an error if there are any missing keys or dynamic variables
# This is useful for CI/CD pipelines to ensure that all translations are consistent
parser = argparse . ArgumentParser ( description = " Generate locale files " )
parser . add_argument (
" --error-on-problems " ,
action = " store_true " ,
help = " Exit with an error if there are any missing keys or dynamic variables " ,
)
parser . add_argument (
" --error-old-dynamic-variables " ,
action = " store_true " ,
help = " Exit with an error if there are any old dynamic variables " ,
)
parser . add_argument (
" --print-problems " ,
action = " store_true " ,
help = " Print the problems table " ,
)
parser . add_argument (
" --print-problem-strings " ,
action = " store_true " ,
help = " Print the problem strings and which locales they are in " ,
)
parser . add_argument (
" --print-problem-formatting-tag-strings " ,
action = " store_true " ,
help = " Print the problem strings and which locales they are in " ,
)
parser . add_argument (
" --write-problems " , action = " store_true " , help = " Write the problems to a file "
)
parser . add_argument (
" --problems-file " ,
default = " ./tools/localization/output/problems.json " ,
help = " The file to write the problems to " ,
)
parser . add_argument (
" --print-old-dynamic-variables " ,
action = " store_true " ,
help = " The file to write the problems to " ,
)
parser . add_argument ( " --en-only " , action = " store_true " , help = " Only check the en locale " )
parser . add_argument ( " --debug " , action = " store_true " , help = " Enable debug mode " )
parser . add_argument (
" --dict-dir " ,
type = str ,
default = " ./_locales "
)
parser . add_argument (
" --dict-file-name " ,
type = str ,
default = " messages.json " ,
)
parser . add_argument (
" --en-file-path " ,
type = str ,
default = " ./_locales/en/messages.json " ,
)
parser . add_argument (
" --generate-types " ,
action = " store_true " ,
help = " Generate the types file " ,
)
args = parser . parse_args ( )
if args . debug :
console . enableDebug ( )
GENERATE_TYPES = args . generate_types
OUTPUT_DIR = " ./ts/localization "
EN_FILE = args . en_file_path
INPUT_DIR = args . dict_dir
# Create a dictionary that maps locale names to their corresponding JSON file data
locales , localeFiles = createMappedJsonFileDictionary ( INPUT_DIR , args . dict_file_name )
if args . en_only :
locales = { " en " : locales [ " en " ] }
# Generate the locales type and write it to a file
if GENERATE_TYPES :
generateTypesOutputMessage = generateLocalesType ( locales [ " en " ] )
console . info ( generateTypesOutputMessage )
localeVariables = dict ( )
localeVariablesOld = dict ( )
locale_b_tags = dict ( )
locale_br_tags = dict ( )
locale_span_tags = dict ( )
locale_disallowed_tags = dict ( )
locale_improper_tags = dict ( )
# Extract the dynamic variables from each locale and store them in a dictionary
for locale , data in locales . items ( ) :
console . debug ( f " Extracting dynamic variables for { locale } " )
(
localeVariables [ locale ] ,
localeVariablesOld [ locale ] ,
) = extractVariablesFromDict ( data )
(
locale_b_tags [ locale ] ,
locale_br_tags [ locale ] ,
locale_span_tags [ locale ] ,
locale_disallowed_tags [ locale ] ,
locale_improper_tags [ locale ] ,
) = extractFormattingTags ( data )
problems = identifyLocaleDynamicVariableDifferences ( localeVariables , locale_b_tags ,
locale_br_tags ,
locale_span_tags , locale_disallowed_tags , locale_improper_tags )
found_old_dynamic_variables = identifyAndPrintOldDynamicVariables (
localeVariablesOld , args . print_old_dynamic_variables
)
# Wrapping up the script and printing out the results
number_of_tag_problems = 0
if problems :
message = " There are issues with the locales. "
if args . print_problem_strings :
string_to_locales = { }
for locale , locale_problems in problems . items ( ) :
if " additional_variables " in locale_problems :
for problem_string in locale_problems [ " additional_variables " ] . keys ( ) :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
if " missing_variables " in locale_problems :
for problem_string in locale_problems [ " missing_variables " ] . keys ( ) :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
if " missing_br_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " missing_br_tags " ] . items ( ) :
if tag_issues > 0 :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
if " missing_b_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " missing_b_tags " ] . items ( ) :
if tag_issues > 0 :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
if " missing_span_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " missing_span_tags " ] . items ( ) :
if tag_issues > 0 :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
if " disallowed_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " disallowed_tags " ] . items ( ) :
if tag_issues > 0 :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
if " improper_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " improper_tags " ] . items ( ) :
if tag_issues > 0 :
if problem_string not in string_to_locales :
string_to_locales [ problem_string ] = [ locale ]
else :
string_to_locales [ problem_string ] . append ( locale )
console . debug ( f " Problem strings: { json . dumps ( string_to_locales , indent = 2 ) } " )
message + = " See above for problem strings and which locales they are in. "
if args . print_problem_formatting_tag_strings :
locales_to_strings = { }
for locale , locale_problems in problems . items ( ) :
locale_missing_br_tags = set ( )
locale_missing_b_tags = set ( )
locale_missing_span_tags = set ( )
locale_disallowed_tags = set ( )
locale_improper_tags = set ( )
if " missing_br_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " missing_br_tags " ] . items ( ) :
if tag_issues > 0 :
locale_missing_br_tags . add ( problem_string )
if " missing_b_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " missing_b_tags " ] . items ( ) :
if tag_issues > 0 :
locale_missing_b_tags . add ( problem_string )
if " missing_span_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " missing_span_tags " ] . items ( ) :
if tag_issues > 0 :
locale_missing_span_tags . add ( problem_string )
if " disallowed_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " disallowed_tags " ] . items ( ) :
if tag_issues > 0 :
locale_disallowed_tags . add ( problem_string )
if " improper_tags " in locale_problems :
for problem_string , tag_issues in locale_problems [ " improper_tags " ] . items ( ) :
if tag_issues > 0 :
locale_improper_tags . add ( problem_string )
locales_to_strings [ locale ] = {
" br " : list ( locale_missing_br_tags ) ,
" b " : list ( locale_missing_b_tags ) ,
" span " : list ( locale_missing_span_tags ) ,
" disallowed_tags " : list ( locale_disallowed_tags ) ,
" improper_tags " : list ( locale_improper_tags ) ,
}
if locales_to_strings [ locale ] [ " br " ] == [ ] :
del locales_to_strings [ locale ] [ " br " ]
if locales_to_strings [ locale ] [ " b " ] == [ ] :
del locales_to_strings [ locale ] [ " b " ]
if locales_to_strings [ locale ] [ " span " ] == [ ] :
del locales_to_strings [ locale ] [ " span " ]
if locales_to_strings [ locale ] [ " disallowed_tags " ] == [ ] :
del locales_to_strings [ locale ] [ " disallowed_tags " ]
if locales_to_strings [ locale ] [ " improper_tags " ] == [ ] :
del locales_to_strings [ locale ] [ " improper_tags " ]
console . info ( f " Problem strings: { json . dumps ( locales_to_strings , indent = 2 ) } " )
message + = " See above for problem strings and which locales they are in. "
for locale , locale_strings in locales_to_strings . items ( ) :
printed_locale = False
printed_problem_strings = set ( )
for tag_type , tag_strings in locale_strings . items ( ) :
if tag_strings :
if locale in ignored_strings_formatting and tag_strings == ignored_strings_formatting [ locale ] :
continue
if not printed_locale :
print ( f " { locale } " )
printed_locale = True
for tag_string in tag_strings :
if tag_string not in printed_problem_strings :
printed_problem_strings . add ( tag_string )
number_of_tag_problems + = 1
print (
f " - [ { tag_string } ](https://crowdin.com/editor/session-crossplatform-strings/300/en- { locale . replace ( ' - ' , ' ' ) . replace ( ' _ ' , ' ' ) . lower ( ) } ?view=comfortable&filter=basic&value=3#q= { tag_string } ) " )
print ( f " Total Problems: { number_of_tag_problems } " )
if args . print_problems :
prettyPrintIssuesTable ( problems )
message + = " See above for details. "
if args . write_problems :
writeFile ( args . problems_file , json . dumps ( problems , indent = 2 ) )
console . info ( f " Problems written to { args . problems_file } " )
message + = f " Problems written to { args . problems_file } "
if not args . print_problems and not args . write_problems :
message + = " Run the script with --print-problems or --write-problems to see the problems. "
console . warn ( message )
if found_old_dynamic_variables :
warning_message = (
" Old dynamic variables were found in the locales. Please update the locales to use the new dynamic variables. "
)
if args . print_old_dynamic_variables :
if args . print_problems :
warning_message + = " See above for details (before the problems table). "
else :
warning_message + = " See above for details. "
else :
warning_message + = " Run the script with --print-old-dynamic-variables to see the old dynamic variables. "
console . warn ( warning_message )
console . debug ( " Locales generation complete " )
timer . stop ( )
if args . error_on_problems :
missing_keys_all = 0
additional_keys_all = 0
missing_variables_all = 0
additional_variables_all = 0
for locale_name , locale_issues in problems . items ( ) :
if locale_name == " en " :
continue
missing_keys_all + = len ( locale_issues . get ( " missing_keys " , [ ] ) )
additional_keys_all + = len ( locale_issues . get ( " additional_keys " , [ ] ) )
missing_variables_all + = sum (
len ( v ) for v in locale_issues . get ( " missing_variables " , { } ) . values ( )
)
additional_variables_all + = sum (
len ( v ) for v in locale_issues . get ( " additional_variables " , { } ) . values ( )
)
EXIT_CODE = 0
if missing_keys_all > 0 :
console . log ( f " Missing keys: { missing_keys_all } " )
if additional_keys_all > 0 :
console . log ( f " Additional keys: { additional_keys_all } " )
if missing_variables_all > 0 :
console . log ( f " Missing variables: { missing_variables_all } " )
EXIT_CODE = 1
if additional_variables_all > 0 :
console . log ( f " Additional variables: { additional_variables_all } " )
EXIT_CODE = 1
if number_of_tag_problems > 0 :
console . log ( f " Formatting issues: { number_of_tag_problems } " )
EXIT_CODE = 1
sys . exit ( EXIT_CODE )
sys . exit ( 0 )