Commit be26836f authored by Brendan Burns's avatar Brendan Burns Committed by Brendan Burns

Update extraction script, sort messages, add .pot file.

parent 17375fc5
#!/bin/bash
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
KUBECTL_FILES="pkg/kubectl/cmd/*.go pkg/kubectl/cmd/*/*.go"
generate_pot="false"
generate_mo="false"
while getopts "hf:xg" opt; do
case $opt in
h)
echo "$0 [-f files] [-x] [-g]"
echo " -f <file-path>: Files to process"
echo " -x extract strings to a POT file"
echo " -g sort .po files and generate .mo files"
exit 0
;;
f)
KUBECTL_FILES="${OPTARG}"
;;
x)
generate_pot="true"
;;
g)
generate_mo="true"
;;
\?)
echo "[-f <files>] -x -g" >&2
exit 1
;;
esac
done
if ! which go-xgettext > /dev/null; then
echo 'Can not find go-xgettext, install with:'
echo 'go get github.com/gosexy/gettext/go-xgettext'
exit 1
fi
if ! which msgfmt > /dev/null; then
echo 'Can not find msgfmt, install with:'
echo 'apt-get install gettext'
exit 1
fi
if [[ "${generate_pot}" == "true" ]]; then
echo "Extracting strings to POT"
go-xgettext -k=i18n.T ${KUBECTL_FILES} > tmp.pot
msgcat -s tmp.pot > translations/kubectl/template.pot
rm tmp.pot
fi
if [[ "${generate_mo}" == "true" ]]; then
echo "Generating .po and .mo files"
for x in translations/*/*/*/*.po; do
msgcat -s $x > tmp.po
mv tmp.po $x
echo "generating .mo file for: $x"
msgfmt $x -o "$(dirname $x)/$(basename $x .po).mo"
done
fi
./hack/generate-bindata.sh
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -120,9 +120,9 @@ func LoadTranslations(root string, getLanguageFn func() string) error {
// and plural translation is used.
func T(defaultValue string, args ...int) string {
if len(args) == 0 {
return gettext.PGettext(defaultValue, defaultValue)
return gettext.PGettext("", defaultValue)
}
return fmt.Sprintf(gettext.PNGettext(defaultValue, defaultValue, defaultValue+".plural", args[0]),
return fmt.Sprintf(gettext.PNGettext("", defaultValue, defaultValue+".plural", args[0]),
args[0])
}
......
......@@ -10,16 +10,35 @@ no need to update `translations/test/...` which is only used for unit tests.
There is an example [PR here](https://github.com/kubernetes/kubernetes/pull/40645) which adds support for French.
Move on to Adding new translations
Once you've added a new language, you'll need to register it in
`pkg/util/i18n/i18n.go` by adding it to the `knownTranslations` map.
## Wrapping strings
There is a simple script in `translations/extract.py` that performs
simple regular expression based wrapping of strings. It can always
use improvements to understand additional strings.
## Extracting strings
Once the strings are wrapped, you can extract strings from go files using
the `go-xgettext` command which can be installed with:
```console
go get github.com/gosexy/gettext/tree/master/go-xgettext
```
Once that's installed you can run `hack/update-translations.sh`, which
will extract and sort any new strings.
## Adding new translations
Edit the appropriate `k8s.po` file, `poedit` is a popular open source tool
for translations.
for translations. You can load the `translations/kubectl/template.pot` file
to find messages that might be missing.
Once you are done with your `.po` file, generate the corresponding `k8s.mo`
file. `poedit` does this automatically on save.
file. `poedit` does this automatically on save, but you can also use
`hack/update-translations.sh` to perform the `po` to `mo` translation.
We use the English translation as both the `msg_id` and the `msg_context`.
We use the English translation as the `msgid`.
## Regenerating the bindata file
Run `./hack/generate-bindata.sh, this will turn the translation files
......
......@@ -34,14 +34,10 @@ class MatchHandler(object):
self.regex = re.compile(regex)
self.replace_fn = replace_fn
# global holding all strings discovered
STRINGS = []
def short_replace(match, file, line_number):
"""Replace a Short: ... cobra command description with an internationalization
"""
sys.stdout.write('{}i18n.T({}),\n'.format(match.group(1), match.group(2)))
STRINGS.append((match.group(2), file, line_number))
SHORT_MATCH = MatchHandler(r'(\s+Short:\s+)("[^"]+"),', short_replace)
......@@ -54,6 +50,14 @@ def import_replace(match, file, line_number):
IMPORT_MATCH = MatchHandler('(.*"k8s.io/kubernetes/pkg/kubectl/cmd/util")', import_replace)
def string_flag_replace(match, file, line_number):
"""Replace a cmd.Flags().String("...", "", "...") with an internationalization
"""
sys.stdout.write('{}i18n.T("{})"))\n'.format(match.group(1), match.group(2)))
STRING_FLAG_MATCH = MatchHandler('(\s+cmd\.Flags\(\).String\("[^"]*", "[^"]*", )"([^"]*)"\)', string_flag_replace)
def replace(filename, matchers):
"""Given a file and a set of matchers, run those matchers
across the file and replace it with the results.
......@@ -75,22 +79,6 @@ def replace(filename, matchers):
# gofmt the file again
from subprocess import call
call(["gofmt", "-s", "-w", filename])
# update the translation files
translation_files = [
"translations/kubectl/default/LC_MESSAGES/k8s.po",
"translations/kubectl/en_US/LC_MESSAGES/k8s.po",
]
for translation_filename in translation_files:
with open(translation_filename, "a") as tfile:
for translation_string in STRINGS:
msg_string = translation_string[0]
tfile.write('\n')
tfile.write('# https://github.com/kubernetes/kubernetes/blob/master/{}#L{}\n'.format(translation_string[1], translation_string[2]))
tfile.write('msgctxt {}\n'.format(msg_string))
tfile.write('msgid {}\n'.format(msg_string))
tfile.write('msgstr {}\n'.format(msg_string))
call(["goimports", "-w", filename])
replace(sys.argv[1], [SHORT_MATCH, IMPORT_MATCH])
replace(sys.argv[1], [SHORT_MATCH, IMPORT_MATCH, STRING_FLAG_MATCH])
......@@ -19,96 +19,78 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language: fr\n"
msgctxt "Update the annotations on a resource"
msgid "Update the annotations on a resource"
msgstr "Mettre à jour les annotations d'une ressource"
msgctxt ""
"watch is only supported on individual resources and resource collections - "
"%d resources were found"
msgid ""
"watch is only supported on individual resources and resource collections - "
"%d resources were found"
msgid_plural ""
"watch is only supported on individual resources and resource collections - "
"%d resources were found"
msgstr[0] ""
"watch n'est compatible qu'avec les ressources individuelles et les "
"collections de ressources. - %d ressource a été trouvée. "
msgstr[1] ""
"watch n'est compatible qu'avec les ressources individuelles et les "
"collections de ressources. - %d ressources ont été trouvées. "
# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98
msgctxt "Apply a configuration to a resource by filename or stdin"
msgid "Apply a configuration to a resource by filename or stdin"
msgstr ""
"Appliquer une configuration à une ressource par nom de fichier ou depuis "
"stdin"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39
msgctxt "Modify kubeconfig files"
msgid "Modify kubeconfig files"
msgstr "Modifier des fichiers kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103
msgctxt "Sets a user entry in kubeconfig"
msgid "Sets a user entry in kubeconfig"
msgstr "Définit un utilisateur dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67
msgctxt "Sets a cluster entry in kubeconfig"
msgid "Sets a cluster entry in kubeconfig"
msgstr "Définit un cluster dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57
msgctxt "Sets a context entry in kubeconfig"
msgid "Sets a context entry in kubeconfig"
msgstr "Définit un contexte dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48
msgctxt "Displays the current-context"
msgid "Displays the current-context"
msgstr "Affiche le contexte actuel"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38
msgctxt "Delete the specified cluster from the kubeconfig"
msgid "Delete the specified cluster from the kubeconfig"
msgstr "Supprimer le cluster spécifié du kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38
msgctxt "Delete the specified context from the kubeconfig"
msgid "Delete the specified context from the kubeconfig"
msgstr "Supprimer le contexte spécifié du kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62
msgid "Describe one or many contexts"
msgstr "Décrire un ou plusieurs contextes"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40
msgctxt "Display clusters defined in the kubeconfig"
msgid "Display clusters defined in the kubeconfig"
msgstr "Afficher les cluster définis dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62
msgctxt "Describe one or many contexts"
msgid "Describe one or many contexts"
msgstr "Décrire un ou plusieurs contextes"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64
msgid "Display merged kubeconfig settings or a specified kubeconfig file"
msgstr ""
"Afficher les paramètres fusionnés de kubeconfig ou d'un fichier kubeconfig "
"spécifié"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48
msgid "Displays the current-context"
msgstr "Affiche le contexte actuel"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39
msgid "Modify kubeconfig files"
msgstr "Modifier des fichiers kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67
msgid "Sets a cluster entry in kubeconfig"
msgstr "Définit un cluster dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57
msgid "Sets a context entry in kubeconfig"
msgstr "Définit un contexte dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103
msgid "Sets a user entry in kubeconfig"
msgstr "Définit un utilisateur dans kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59
msgctxt "Sets an individual value in a kubeconfig file"
msgid "Sets an individual value in a kubeconfig file"
msgstr "Définit une valeur individuelle dans un fichier kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48
msgid "Sets the current-context in a kubeconfig file"
msgstr "Définit le contexte courant dans un fichier kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47
msgctxt "Unsets an individual value in a kubeconfig file"
msgid "Unsets an individual value in a kubeconfig file"
msgstr "Supprime une valeur individuelle dans un fichier kubeconfig"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48
msgctxt "Sets the current-context in a kubeconfig file"
msgid "Sets the current-context in a kubeconfig file"
msgstr "Définit le contexte courant dans un fichier kubeconfig"
msgid "Update the annotations on a resource"
msgstr "Mettre à jour les annotations d'une ressource"
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64
msgctxt "Display merged kubeconfig settings or a specified kubeconfig file"
msgid "Display merged kubeconfig settings or a specified kubeconfig file"
msgstr ""
"Afficher les paramètres fusionnés de kubeconfig ou d'un fichier kubeconfig "
"spécifié"
msgid ""
"watch is only supported on individual resources and resource collections - "
"%d resources were found"
msgid_plural ""
"watch is only supported on individual resources and resource collections - "
"%d resources were found"
msgstr[0] ""
"watch n'est compatible qu'avec les ressources individuelles et les "
"collections de ressources. - %d ressource a été trouvée. "
msgstr[1] ""
"watch n'est compatible qu'avec les ressources individuelles et les "
"collections de ressources. - %d ressources ont été trouvées. "
......@@ -19,12 +19,10 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: en\n"
msgctxt "test_string"
msgid "test_string"
msgstr "foo"
msgctxt "test_plural"
msgid "test_plural"
msgid_plural "test_plural"
msgstr[0] "there was %d item"
msgstr[1] "there were %d items"
msgid "test_string"
msgstr "foo"
......@@ -19,12 +19,10 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: en\n"
msgctxt "test_string"
msgid "test_string"
msgstr "baz"
msgctxt "test_plural"
msgid "test_plural"
msgid_plural "test_plural"
msgstr[0] "there was %d item"
msgstr[1] "there were %d items"
msgid "test_string"
msgstr "baz"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment