diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index a017efab..31f22997 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -9,6 +9,9 @@ on: - 'locale/sunshine.po' workflow_dispatch: +env: + file: ./locale/sunshine.po + jobs: localize: name: Update Localization @@ -37,9 +40,20 @@ jobs: - name: Update Strings run: | + # first, try to remove existing file as xgettext does not remove unused translations + if [ -f "${{ env.file }}" ]; + then + rm ${{ env.file }} + echo "new_file=false" >> $GITHUB_ENV + else + echo "new_file=true" >> $GITHUB_ENV + fi + + # extract the new strings python ./scripts/_locale.py --extract - name: git diff + if: ${{ env.new_file == 'false' }} run: | # disable the pager git config --global pager.diff false @@ -52,7 +66,8 @@ jobs: echo "git_diff=${OUTPUT}" >> $GITHUB_ENV - name: git reset - if: ${{ env.git_diff == '1 1 locale/sunshine.po' }} # only run if more than 1 line changed + # only run if a single line changed (date/time) and file already existed + if: ${{ env.git_diff == '1 1 locale/sunshine.po' && env.new_file == 'false' }} run: | git reset --hard diff --git a/docs/source/contributing/localization.rst b/docs/source/contributing/localization.rst index 721ebc61..8127eda3 100644 --- a/docs/source/contributing/localization.rst +++ b/docs/source/contributing/localization.rst @@ -54,6 +54,9 @@ situations. For example if a system tray icon is added it should be localized as #include boost::locale::translate("Hello world!") + .. Tip:: More examples can be found in the documentation for + `boost locale `_. + .. Warning:: This is for information only. Contributors should never include manually updated template files, or manually compiled language files in Pull Requests. @@ -67,7 +70,8 @@ any of the following paths are modified. - 'sunshine/**' When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is -required for this, along with the dependencies in the `./scripts/requirements.txt` file. +required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally, +`xgettext `_ must be installed. Extract, initialize, and update .. code-block:: bash diff --git a/scripts/_locale.py b/scripts/_locale.py index e47887cc..339e2d4a 100644 --- a/scripts/_locale.py +++ b/scripts/_locale.py @@ -13,6 +13,7 @@ import os import subprocess project_name = 'Sunshine' +project_owner = 'SunshineStream' script_dir = os.path.dirname(os.path.abspath(__file__)) root_dir = os.path.dirname(script_dir) @@ -37,22 +38,30 @@ target_locales = [ def x_extract(): """Executes `xgettext extraction` in subprocess.""" + pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.po') + commands = [ 'xgettext', + '--keyword=translate:1,1t', + '--keyword=translate:1c,2,2t', + '--keyword=translate:1,2,3t', + '--keyword=translate:1c,2,3,4t', + '--keyword=gettext:1', + '--keyword=pgettext:1c,2', + '--keyword=ngettext:1,2', + '--keyword=npgettext:1c,2,3', f'--default-domain={project_name.lower()}', - f'--output={os.path.join(locale_dir, project_name.lower() + ".po")}', + f'--output={pot_filepath}', '--language=C++', '--boost', '--from-code=utf-8', '-F', - f'--msgid-bugs-address=github.com/{project_name.lower()}', - f'--copyright-holder={project_name}', + f'--msgid-bugs-address=github.com/{project_owner.lower()}/{project_name.lower()}', + f'--copyright-holder={project_owner}', f'--package-name={project_name}', '--package-version=v0' ] - pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.po') - extensions = ['cpp', 'h', 'm', 'mm'] # find input files @@ -66,23 +75,26 @@ def x_extract(): print(commands) subprocess.check_output(args=commands, cwd=root_dir) - # fix header - body = "" - with open(file=pot_filepath, mode='r') as file: - for line in file.readlines(): - if line != '"Language: \\n"\n': # do not include this line - if line == '# SOME DESCRIPTIVE TITLE.\n': - body += f'# Translations template for {project_name}.\n' - elif line.startswith('#') and 'YEAR' in line: - body += line.replace('YEAR', str(year)) - elif line.startswith('#') and 'PACKAGE' in line: - body += line.replace('PACKAGE', project_name) - else: - body += line + try: + # fix header + body = "" + with open(file=pot_filepath, mode='r') as file: + for line in file.readlines(): + if line != '"Language: \\n"\n': # do not include this line + if line == '# SOME DESCRIPTIVE TITLE.\n': + body += f'# Translations template for {project_name}.\n' + elif line.startswith('#') and 'YEAR' in line: + body += line.replace('YEAR', str(year)) + elif line.startswith('#') and 'PACKAGE' in line: + body += line.replace('PACKAGE', project_name) + else: + body += line - # rewrite pot file with updated header - with open(file=pot_filepath, mode='w+') as file: - file.write(body) + # rewrite pot file with updated header + with open(file=pot_filepath, mode='w+') as file: + file.write(body) + except FileNotFoundError: + pass def babel_init(locale_code: str):