Skip to content

Commit

Permalink
feat: Support I18N
Browse files Browse the repository at this point in the history
Fixes #42.

Signed-off-by: 林博仁(Buo-ren Lin) <[email protected]>
  • Loading branch information
brlin-tw committed Nov 28, 2021
1 parent ced86af commit 09f06ab
Show file tree
Hide file tree
Showing 8 changed files with 445 additions and 136 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 16,7 @@
/.* export-ignore
/continuous-integration/ export-ignore
/distribution/ export-ignore
/dev-assets/ export-ignore

# Exclude development assets exclusive licenses
/LICENSES/WTFPL.* export-ignore
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 73,9 @@

# Don't track Vagrant runtime directories
.vagrant/

# Don't track GNU gettext message catalog template
*.pot

# Don't track GNU gettext machine-readable message catalogs
*.mo
7 changes: 6 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 15,12 @@ Contribution is always welcomed in WoeUSB! However, please review the following

## Contributing to the localization(L10N) of the product

Currently there is no internationalization(I18N) infrastructure implemented in this project, patches are welcome!
* We use [GNU gettext](https://www.gnu.org/software/gettext/) to support internationalization(I18N), please check out [their documentation](https://www.gnu.org/software/gettext/manual/) for the overall process.
* Check out the following utility scripts for generating the files required for translation.
[dev-assets/build-gettext-template.sh](dev-assets/build-gettext-template.sh)
[dev-assets/initialize-new-message-catalog-locale.sh](dev-assets/initialize-new-message-catalog-locale.sh)
[dev-assets/build-binary-message-catalogs.sh](dev-assets/build-binary-message-catalogs.sh)
* We require all contribution's revision commits to be signed with [Developer Certificate of Origin](https://developercertificate.org/).

## Contributing to the documentation

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 63,8 @@ Without the following dependencies WoeUSB will still able to run, but some funct
For workaround the problem where the Windows 7 installation media doesn't ship their UEFI bootloader in the proper location
* [Pete Batard](https://pete.akeo.ie/)'s [UEFI:NTFS](https://github.com/pbatard/uefi-ntfs) UEFI bootloader
For supporting NTFS filesystems in the target USB key
* [GNU gettext](https://www.gnu.org/software/gettext/)
For supporting message internationalization(I18N)

## Installation

Expand Down
75 changes: 75 additions & 0 deletions dev-assets/build-binary-message-catalogs.sh
Original file line number Diff line number Diff line change
@@ -0,0 1,75 @@
#!/usr/bin/env bash
# Build machine-readable message catalogs from their textual counterparts
#
# Copyright © 2021 WoeUSB project contributors
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Reference:
#
# * GNU gettext utilities: msgfmt Invocation
# https://www.gnu.org/software/gettext/manual/html_node/msgfmt-Invocation.html#msgfmt-Invocation
set \
-o errexit \
-o nounset

if test "${#}" -ne 0; then
printf \
'Usage: %s\n' \
"${0}"
exit 1
fi

declare -A dependencies=(
[coreutils]='Coreutils - GNU core utilities <https://www.gnu.org/software/coreutils/>'
[gettext]='GNU gettext <https://www.gnu.org/software/gettext/>'
)
declare -A required_commands=(
[mkdir]="${dependencies[coreutils]}"
[msgfmt]="${dependencies[gettext]}"
[realpath]="${dependencies[coreutils]}"
)
dependency_check_failed=false
for required_command in "${!required_commands[@]}"; do
if ! command -v "${required_command}" >/dev/null; then
printf \
'Error: This program requires the "%s" command to be available in your command search PATHs.\n' \
"${required_command}" \
1>&2
dependency_check_failed=true
fi
done
if test "${dependency_check_failed}" == true; then
exit 2
fi

script="$(
realpath \
--strip \
"${BASH_SOURCE[0]}"
)"
script_dir="${script%/*}"
project_dir="$(
realpath \
--strip \
"${script_dir%/*}"
)"
locale_dir="${project_dir}/share/locale"

shopt \
-s \
globstar \
nullglob

pushd "${locale_dir}" >/dev/null
for po_file in **/*.po; do
mo_file="${po_file%.po}.mo"
msgfmt \
--check \
--output-file="${mo_file}" \
--statistics \
"${po_file}"
done
popd >/dev/null

printf \
'Info: Machine-readable message catalogs built successfully\n'
96 changes: 96 additions & 0 deletions dev-assets/build-gettext-template.sh
Original file line number Diff line number Diff line change
@@ -0,0 1,96 @@
#!/usr/bin/env bash
# Build gettext translatable messages template
#
# Copyright © 2021 WoeUSB project contributors
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Reference:
#
# * GNU gettext utilities: msginit Invocation
# https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html#msginit-Invocation
set \
-o errexit \
-o nounset

if test "${#}" -ne 0; then
printf \
'Usage: %s\n' \
"${0}"
exit 1
fi

declare -A dependencies=(
[coreutils]='Coreutils - GNU core utilities <https://www.gnu.org/software/coreutils/>'
[gettext]='GNU gettext <https://www.gnu.org/software/gettext/>'
[git]='Git <https://git-scm.com/>'
[sed]='GNU sed <https://www.gnu.org/software/sed/>'
)
declare -A required_commands=(
[git]="${dependencies[git]}"
[mkdir]="${dependencies[coreutils]}"
[realpath]="${dependencies[coreutils]}"
[sed]="${dependencies[sed]}"
[xgettext]="${dependencies[gettext]}"
)
dependency_check_failed=false
for required_command in "${!required_commands[@]}"; do
if ! command -v "${required_command}" >/dev/null; then
printf \
'Error: This program requires the "%s" command to be available in your command search PATHs.\n' \
"${required_command}" \
1>&2
dependency_check_failed=true
fi
done
if test "${dependency_check_failed}" == true; then
exit 2
fi

script="$(
realpath \
--strip \
"${BASH_SOURCE[0]}"
)"
script_dir="${script%/*}"
project_dir="$(
realpath \
--strip \
"${script_dir%/*}"
)"
git_describe="$(
git describe \
--always \
--dirty \
--tags
)"
project_version="${git_describe#v}"
locale_dir="${project_dir}/share/locale"
mkdir \
--parents \
--verbose \
"${locale_dir}"
template="${locale_dir}/woeusb.pot"

pushd "${project_dir}" >/dev/null
xgettext \
--copyright-holder='WoeUSB contributors <https://github.com/WoeUSB/WoeUSB/graphs/contributors>' \
--language=Shell \
--msgid-bugs-address=https://github.com/WoeUSB/WoeUSB/issues \
--output="${template}" \
--package-name=woeusb \
--package-version="${project_version}" \
./sbin/woeusb
popd >/dev/null

# False positive: Workaround "reuse._util - ERROR - Could not parse 'GPL-3.0-or-later/' \'" error
sed \
--in-place \
--expression 's/SOME DESCRIPTIVE TITLE\./GNU gettext message catalog template for WoeUSB/' \
--expression "s/Copyright (C) YEAR/Copyright (C) $(date %Y)/" \
--expression 's/CHARSET/UTF-8/' \
--expression 's/This file is distributed under the same license as the woeusb package./SPDX''-License-Identifier: GPL-3.0-or-later/' \
"${template}"

printf \
'Info: Template generated at "%s"\n' \
"${template}"
110 changes: 110 additions & 0 deletions dev-assets/initialize-new-message-catalog-locale.sh
Original file line number Diff line number Diff line change
@@ -0,0 1,110 @@
#!/usr/bin/env bash
# Initialize new gettext message catalog for specified locale
#
# Copyright © 2021 WoeUSB project contributors
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Reference:
#
# * GNU gettext utilities: msginit Invocation
# https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html#msginit-Invocation
set \
-o errexit \
-o nounset

if test "${#}" -ne 1; then
printf \
'Usage: %s _locale_code_\n' \
"${0}" \
1>&2
exit 1
fi

declare -A dependencies=(
[coreutils]='Coreutils - GNU core utilities <https://www.gnu.org/software/coreutils/>'
[gettext]='GNU gettext <https://www.gnu.org/software/gettext/>'
)
declare -A required_commands=(
[mkdir]="${dependencies[coreutils]}"
[msginit]="${dependencies[gettext]}"
[realpath]="${dependencies[coreutils]}"
)
dependency_check_failed=false
for required_command in "${!required_commands[@]}"; do
if ! command -v "${required_command}" >/dev/null; then
printf \
'Error: This program requires the "%s" command to be available in your command search PATHs.\n' \
"${required_command}" \
1>&2
dependency_check_failed=true
fi
done
if test "${dependency_check_failed}" == true; then
exit 2
fi

locale_code="${1}"; shift

if [[ ! ${locale_code} =~ [[:alpha:]]{2}_[[:alpha:]]{2}(\.. )? ]]; then
# false positive: not a command substitution
# shellcheck disable=SC2016
printf \
'Error: Invalid locale code "%s", refer the `--locale` command option of the msginit(1) manual page for the specification.\n' \
"${locale_code}" \
1>&2
exit 3
fi

script="$(
realpath \
--strip \
"${BASH_SOURCE[0]}"
)"
script_dir="${script%/*}"
project_dir="$(
realpath \
--strip \
"${script_dir%/*}"
)"

# NOTE: Basic Shell Features » Shell Expansions » '${PARAMETER/PATTERN/STRING}'
if test "${project_dir// }" != "${project_dir}"; then
printf \
"Warning: Space character is detected in the project path, which may trigger msginit's bug. Try to move/mount it to a safe path if you encounter errors.\\n" \
1>&2
fi

locale_dir="${project_dir}/share/locale"
mkdir \
--parents \
--verbose \
"${locale_dir}"
template="${locale_dir}/woeusb.pot"

if ! test -e "${template}"; then
printf \
'Error: Message catalog template file not exist, please generate it by running %s beforehand.\n' \
"${script_dir}/build-gettext-template.sh" \
1>&2
exit 4
fi

locale_messages_dir="${locale_dir}/${locale_code}/LC_MESSAGES"
mkdir \
--parents \
--verbose \
"${locale_messages_dir}"
message_catalog="${locale_messages_dir}/woeusb.po"
msginit \
--input="${project_dir}/share/locale/woeusb.pot" \
--locale="${locale_code}" \
--output="${message_catalog}"

sed \
--in-place \
--expression "s/ template/(${locale_code})/" \
"${message_catalog}"

printf \
'Info: Initialization successful, message catalog generated at "%s"\n' \
"${message_catalog}"
Loading

0 comments on commit 09f06ab

Please sign in to comment.