Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/tools/i18n/generateLongStringTranslations.py
#!/usr/bin/env python2 | #!/usr/bin/env python3 | ||||
# -*- coding:utf-8 -*- | |||||
# | # | ||||
# Copyright (C) 2014 Wildfire Games. | # Copyright (C) 2020 Wildfire Games. | ||||
# This file is part of 0 A.D. | # This file is part of 0 A.D. | ||||
# | # | ||||
# 0 A.D. is free software: you can redistribute it and/or modify | # 0 A.D. is free software: you can redistribute it and/or modify | ||||
# it under the terms of the GNU General Public License as published by | # it under the terms of the GNU General Public License as published by | ||||
# the Free Software Foundation, either version 2 of the License, or | # the Free Software Foundation, either version 2 of the License, or | ||||
# (at your option) any later version. | # (at your option) any later version. | ||||
# | # | ||||
# 0 A.D. is distributed in the hope that it will be useful, | # 0 A.D. is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | # GNU General Public License for more details. | ||||
# | # | ||||
# You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||
# along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | # along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
from __future__ import absolute_import, division, print_function, unicode_literals | import os, sys | ||||
import multiprocessing | |||||
import codecs, json, os, sys, textwrap | from i18n_helper import l10nToolsDirectory, projectRootDirectory | ||||
from i18n_helper.catalog import Catalog | |||||
from i18n_helper.globber import getCatalogs | |||||
from pology.catalog import Catalog | |||||
from pology.message import Message | |||||
l10nToolsDirectory = os.path.dirname(os.path.realpath(__file__)) | |||||
projectRootDirectory = os.path.abspath(os.path.join(l10nToolsDirectory, os.pardir, os.pardir, os.pardir)) | |||||
l10nFolderName = "l10n" | l10nFolderName = "l10n" | ||||
def generateLongStringTranslationFromPotIntoPo(inputFilePath, outputFilePath): | def generateLongStringTranslationFromPotIntoPo(inputFilePath, outputFilePath): | ||||
templateCatalog = Catalog.readFrom(inputFilePath) | |||||
templateCatalog = Catalog(inputFilePath) | longStringCatalog = Catalog(locale="en") # Pretend we write English to get plurals. | ||||
longStringCatalog = Catalog(outputFilePath, create=True, truncate=True) | |||||
# Fill catalog with English strings. | # Fill catalog with English strings. | ||||
for message in templateCatalog: | for message in templateCatalog: | ||||
longStringCatalog.add(message) | longStringCatalog.add(id=message.id, string=message.id, context=message.context) | ||||
# If language codes were specified on the command line, filder by those. | # If language codes were specified on the command line, filder by those. | ||||
filters = sys.argv[1:] | filters = sys.argv[1:] | ||||
# Load existing translation catalogs. | # Load existing translation catalogs. | ||||
existingTranslationCatalogs = [] | existingTranslationCatalogs = getCatalogs(inputFilePath, filters) | ||||
l10nFolderPath = os.path.dirname(inputFilePath) | |||||
# .pot is one letter longer than .po, but the dot that separates the locale | |||||
# code from the rest of the filename in .po files makes up for that. | |||||
charactersToSkip = len(os.path.basename(inputFilePath)) | |||||
for filename in os.listdir(l10nFolderPath): | |||||
if len(filename) > 3 and filename[-3:] == ".po" and filename[:4] != "long": | |||||
if not filters or filename[:-charactersToSkip] in filters: | |||||
if os.path.basename(inputFilePath)[:-4] == filename.split('.')[-2]: | |||||
existingTranslationCatalogs.append(os.path.join(l10nFolderPath, filename)) | |||||
# If any existing translation has more characters than the average expansion, use that instead. | # If any existing translation has more characters than the average expansion, use that instead. | ||||
for pofile in existingTranslationCatalogs: | for translationCatalog in existingTranslationCatalogs: | ||||
print(u"Merging", pofile) | |||||
translationCatalog = Catalog(pofile) | |||||
for longStringCatalogMessage in longStringCatalog: | for longStringCatalogMessage in longStringCatalog: | ||||
translationMessage = translationCatalog.select_by_key(longStringCatalogMessage.msgctxt, longStringCatalogMessage.msgid) | translationMessage = translationCatalog.get(longStringCatalogMessage.id, longStringCatalogMessage.context) | ||||
if not translationMessage: | if not translationMessage or not translationMessage.string: | ||||
continue | continue | ||||
if not longStringCatalogMessage.msgid_plural: | if not longStringCatalogMessage.pluralizable or not translationMessage.pluralizable: | ||||
if len(translationMessage[0].msgstr[0]) > len(longStringCatalogMessage.msgstr[0]): | if len(translationMessage.string) > len(longStringCatalogMessage.string): | ||||
longStringCatalogMessage.msgstr = translationMessage[0].msgstr | longStringCatalogMessage.string = translationMessage.string | ||||
translationMessage = longStringCatalogMessage | |||||
continue | continue | ||||
longestSingularString = translationMessage[0].msgstr[0] | longestSingularString = translationMessage.string[0] | ||||
longestPluralString = translationMessage[0].msgstr[1] if len(translationMessage[0].msgstr) > 1 else longestSingularString | longestPluralString = translationMessage.string[1 if len(translationMessage.string) > 1 else 0] | ||||
candidateSingularString = longStringCatalogMessage.msgstr[0] | candidateSingularString = longStringCatalogMessage.string[0] | ||||
candidatePluralString = "" # There might be between 0 and infinite plural forms. | candidatePluralString = "" # There might be between 0 and infinite plural forms. | ||||
for candidateString in longStringCatalogMessage.msgstr[1:]: | for candidateString in longStringCatalogMessage.string[1:]: | ||||
if len(candidateString) > len(candidatePluralString): candidatePluralString = candidateString | if len(candidateString) > len(candidatePluralString): | ||||
candidatePluralString = candidateString | |||||
changed = False | changed = False | ||||
if len(candidateSingularString) > len(longestSingularString): | if len(candidateSingularString) > len(longestSingularString): | ||||
longestSingularString = candidateSingularString | longestSingularString = candidateSingularString | ||||
changed = True | changed = True | ||||
if len(candidatePluralString) > len(longestPluralString): | if len(candidatePluralString) > len(longestPluralString): | ||||
longestPluralString = candidatePluralString | longestPluralString = candidatePluralString | ||||
changed = True | changed = True | ||||
if changed: | if changed: | ||||
longStringCatalogMessage.msgstr = [longestSingularString, longestPluralString] | longStringCatalogMessage.string = [longestSingularString, longestPluralString] | ||||
translationMessage = longStringCatalogMessage | translationMessage = longStringCatalogMessage | ||||
longStringCatalog.writeTo(outputFilePath) | |||||
longStringCatalog.set_encoding("utf-8") | |||||
longStringCatalog.sync() | |||||
def main(): | def main(): | ||||
foundPots = 0 | foundPots = 0 | ||||
for root, folders, filenames in os.walk(projectRootDirectory): | for root, folders, filenames in os.walk(projectRootDirectory): | ||||
root = root.decode("utf-8") | |||||
for filename in filenames: | for filename in filenames: | ||||
if len(filename) > 4 and filename[-4:] == ".pot" and os.path.basename(root) == "l10n": | if len(filename) > 4 and filename[-4:] == ".pot" and os.path.basename(root) == "l10n": | ||||
foundPots += 1 | foundPots += 1 | ||||
print(u"Generating", "long." + filename[:-1]) | print("Generating", "long." + filename[:-1]) | ||||
generateLongStringTranslationFromPotIntoPo(os.path.join(root, filename), os.path.join(root, "long." + filename[:-1])) | multiprocessing.Process( | ||||
target=generateLongStringTranslationFromPotIntoPo, | |||||
args=(os.path.join(root, filename), os.path.join(root, "long." + filename[:-1])) | |||||
).start() | |||||
if foundPots == 0: | if foundPots == 0: | ||||
print(u"This script did not work because no ‘.pot’ files were found.") | print("This script did not work because no ‘.pot’ files were found. " | ||||
print(u"Please, run ‘updateTemplates.py’ to generate the ‘.pot’ files, and run ‘pullTranslations.py’ to pull the latest translations from Transifex.") | "Please, run ‘updateTemplates.py’ to generate the ‘.pot’ files, and run ‘pullTranslations.py’ to pull the latest translations from Transifex. " | ||||
print(u"Then you can run this script to generate ‘.po’ files with the longest strings.") | "Then you can run this script to generate ‘.po’ files with the longest strings.") | ||||
if __name__ == "__main__": | if __name__ == "__main__": | ||||
main() | main() |
Wildfire Games · Phabricator