-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
gh-79516: allow msgfmt.py to compile multiple input po files #10875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
s-ball
wants to merge
68
commits into
python:main
Choose a base branch
from
s-ball:multi_inputs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
73b5ac8
Add test for current behaviour of msgfmt.py
s-ball 5fb1575
Final fix for bpo-9741, with tests proving it.
s-ball b1968e9
Update docstrings for the script and make function
s-ball 0bc4ad3
Give make a simpler and more consistent interface.
s-ball a9e67b4
Add a Misc/NEWS.d entry.
s-ball 6c59d6c
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ball 1ce22c0
Merge branch 'main' into multi_inputs
s-ball 863bd97
Merge branch 'main' into multi_inputs
s-ball 4390ede
Fix an import error in test_i18n.py .
s-ball 008ea27
Fix another import error.
s-ball 8744743
Merge branch 'main' into multi_inputs
s-ball 93a6eb7
Merge branch 'main' into multi_inputs
s-ball ba26b80
Revert version number to 1.2
s-ball 150cea1
Merge branch 'main' into multi_inputs
s-ball d9afabb
Merge branch 'main' into multi_inputs
s-ball 9004387
Merge branch 'main' into multi_inputs
s-ball 7556f79
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ball 80947d1
Merge branch 'main' into multi_inputs
s-ball 12acb83
Merge branch 'main' into multi_inputs
s-ball 1ecc1f3
Fix a merge error
s-ball e59ba68
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ball 4ffd20a
Merge branch 'main' into multi_inputs
s-ball 7505f2b
Merge branch 'main' into multi_inputs
s-ball 2c27120
Merge branch 'main' into multi_inputs
s-ball 1f4e5ac
fix details
merwok 4170796
Merge branch 'main' into multi_inputs
s-ball 46c08c5
Move tests for the gh-79516 issue to test_msgfmt.py
s-ball 24d89a6
Cosmetic improvements after review.
s-ball 17b4e05
Fix an import error
s-ball bfc8a44
Merge branch 'main' into multi_inputs
s-ball 106dd40
Apply suggestions from code review
s-ball 9cb9395
Cosmetic improvements after review.
s-ball 08bc8d7
In test_msgfmt move data files to the data folder.
s-ball 9d992cd
Remove duplicate tests from test_msgfmt.
s-ball 31fd434
Merge branch 'main' into multi_inputs
s-ball 916aec7
Merge branch 'main' into multi_inputs
s-ball 51fcf09
Rename data files for test_msgfmt.Test_multi_input
s-ball d51ad50
Apply suggestions from code review
s-ball 677f720
Cosmetic improvements after review.
s-ball b4ea80a
compile_messages now accepts several input files
s-ball 3120add
whitespace nit
merwok d642923
Merge branch 'main' into multi_inputs
s-ball 9d91f12
Make explicit how mo files can be re-generated.
s-ball 4d83cb7
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ball 421272b
Apply suggestions from code review
s-ball 09b97d9
Update Lib/test/test_tools/test_msgfmt.py
s-ball 12cae51
Merge branch 'main' into multi_inputs
s-ball 3760851
Merge branch 'main' into multi_inputs
s-ball d45039c
Generate json files for MultiInputTest data files.
s-ball dde5ef1
Apply suggestions from code review
s-ball bb6e0c5
Cosmetic improvements (long lines...)
s-ball 797990a
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ball c95af16
Merge branch 'main' into multi_inputs
s-ball 905ec70
Revert an unwanted change.
s-ball b7a7c48
Simplifies the general logic of msgfmt.py
s-ball 1b3b73e
Update Tools/i18n/msgfmt.py
s-ball 1db2c66
Changes per review.
s-ball 3a6e1ef
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ball 743bdc5
Removes the now unused get_names function.
s-ball 50e7145
Tests for extension corner cases for msgfmt.py
s-ball caa8955
Merge branch 'main' into multi_inputs
s-ball a4f1769
Fix a parameter inversion in test_msgfmt.py
s-ball 11f6e69
Merge branch 'main' into multi_inputs
s-ball 0ed3107
Merge branch 'main' into multi_inputs
s-ball d1e0a26
Merge branch 'main' into multi_inputs
s-ball 213afcb
Merge branch 'main' into multi_inputs
s-ball 4d54e50
Merge main into multi_inputs
s-ball ab97edd
Merge branch 'main' into multi_inputs
s-ball File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
file1_fr_crlf.po eol=crlf | ||
file2_fr_lf.po eol=lf |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
[ | ||
[ | ||
"", | ||
"Project-Id-Version: PACKAGE VERSION\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 23:57+0100\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: French\nLanguage: fr\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n > 1);\n" | ||
], | ||
[ | ||
"Bye...", | ||
"Au revoir ..." | ||
], | ||
[ | ||
"Hello!", | ||
"Bonjour !" | ||
], | ||
[ | ||
"It's over.", | ||
"C'est termin\u00e9." | ||
], | ||
[ | ||
[ | ||
"{n} horse", | ||
0 | ||
], | ||
"{n} cheval" | ||
], | ||
[ | ||
[ | ||
"{n} horse", | ||
1 | ||
], | ||
"{n} chevaux" | ||
] | ||
] |
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[ | ||
[ | ||
"", | ||
"Project-Id-Version: PACKAGE VERSION\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 23:46+0100\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: French\nLanguage: fr\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n > 1);\n" | ||
], | ||
[ | ||
"Hello!", | ||
"Bonjour !" | ||
], | ||
[ | ||
[ | ||
"{n} horse", | ||
0 | ||
], | ||
"{n} cheval" | ||
], | ||
[ | ||
[ | ||
"{n} horse", | ||
1 | ||
], | ||
"{n} chevaux" | ||
] | ||
] |
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Example of French translations, crlf end of lines | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: PACKAGE VERSION\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2018-11-30 23:46+0100\n" | ||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
"Language-Team: French\n" | ||
"Language: fr\n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: 8bit\n" | ||
"Plural-Forms: nplurals=2; plural=(n > 1);\n" | ||
|
||
#: file1.py:6 | ||
msgid "Hello!" | ||
msgstr "Bonjour !" | ||
|
||
#: file1.py:7 | ||
#, python-brace-format | ||
msgid "{n} horse" | ||
msgid_plural "{n} horses" | ||
msgstr[0] "{n} cheval" | ||
msgstr[1] "{n} chevaux" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[ | ||
[ | ||
"", | ||
"Project-Id-Version: PACKAGE VERSION\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 23:57+0100\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: French\nLanguage: fr\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n > 1);\n" | ||
], | ||
[ | ||
"Bye...", | ||
"Au revoir ..." | ||
], | ||
[ | ||
"It's over.", | ||
"C'est termin\u00e9." | ||
] | ||
] |
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Example of French translations, lf end of lines | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: PACKAGE VERSION\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2018-11-30 23:57+0100\n" | ||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
"Language-Team: French\n" | ||
"Language: fr\n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: 8bit\n" | ||
"Plural-Forms: nplurals=2; plural=(n > 1);\n" | ||
|
||
#: file2.py:6 | ||
msgid "It's over." | ||
msgstr "C'est terminé." | ||
|
||
#: file2.py:7 | ||
msgid "Bye..." | ||
msgstr "Au revoir ..." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,17 @@ | ||
"""Tests for the Tools/i18n/msgfmt.py tool.""" | ||
"""Tests for the Tools/i18n/msgfmt.py tool. | ||
|
||
These tests use data files (po and mo) in the msgfmt_data folder. | ||
The mo files can be generated (if the po file changes, or if msgfmt.py | ||
slightly changes its output format) by using the --snapshot-update flag | ||
with this script: | ||
|
||
python test_msgfmt.py --snapshot-update | ||
""" | ||
|
||
import filecmp | ||
import json | ||
import os.path | ||
import shutil | ||
import struct | ||
import sys | ||
import unittest | ||
|
@@ -11,7 +22,6 @@ | |
from test.support.script_helper import assert_python_failure, assert_python_ok | ||
from test.test_tools import imports_under_tool, skip_if_missing, toolsdir | ||
|
||
|
||
skip_if_missing('i18n') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Accidentally removed line here |
||
|
||
data_dir = (Path(__file__).parent / 'msgfmt_data').resolve() | ||
|
@@ -22,6 +32,10 @@ | |
import msgfmt | ||
|
||
|
||
def compile_many_messages(mo_file, *po_files): | ||
assert_python_ok(msgfmt_py, '-o', mo_file, *po_files) | ||
|
||
|
||
def compile_messages(po_file, mo_file): | ||
assert_python_ok(msgfmt_py, '-o', mo_file, po_file) | ||
|
||
|
@@ -145,12 +159,6 @@ def test_generic_syntax_error(self): | |
|
||
|
||
class POParserTest(unittest.TestCase): | ||
merwok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@classmethod | ||
def tearDownClass(cls): | ||
# msgfmt uses a global variable to store messages, | ||
# clear it after the tests. | ||
msgfmt.MESSAGES.clear() | ||
|
||
def test_strings(self): | ||
# Test that the PO parser correctly handles and unescape | ||
# strings in the PO file. | ||
|
@@ -202,9 +210,7 @@ def test_strings(self): | |
# check the result. | ||
po = f'msgid {po_string}\nmsgstr "translation"' | ||
Path('messages.po').write_text(po) | ||
# Reset the global MESSAGES dictionary | ||
msgfmt.MESSAGES.clear() | ||
msgfmt.make('messages.po', 'messages.mo') | ||
msgfmt.make(('messages.po',), 'messages.mo') | ||
|
||
with open('messages.mo', 'rb') as f: | ||
actual = GNUTranslations(f) | ||
|
@@ -238,7 +244,7 @@ def test_strings(self): | |
# Reset the global MESSAGES dictionary | ||
msgfmt.MESSAGES.clear() | ||
with self.assertRaises(Exception): | ||
msgfmt.make('messages.po', 'messages.mo') | ||
msgfmt.make(('messages.po',), 'messages.mo') | ||
|
||
|
||
class CLITest(unittest.TestCase): | ||
|
@@ -271,20 +277,83 @@ def test_nonexistent_file(self): | |
assert_python_failure(msgfmt_py, 'nonexistent.po') | ||
|
||
|
||
class MultiInputTest(unittest.TestCase): | ||
"""Tests for multiple input files | ||
""" | ||
|
||
def test_both_with_outputfile(self): | ||
"""Test script with -o option and 2 input files | ||
|
||
The current behaviour is to merge entries having distinct ids | ||
and keep last one if the same id occurs in multiple files. | ||
|
||
Here the first file has Windows endings (cflr) while second has | ||
Unix endings (lf) | ||
""" | ||
with temp_cwd(None): | ||
assert_python_ok(msgfmt_py, '-o', 'file12.mo', | ||
data_dir / 'file1_fr_crlf.po', | ||
data_dir / 'file2_fr_lf.po') | ||
self.assertTrue(filecmp.cmp(data_dir / 'file12_fr.mo', | ||
'file12.mo')) | ||
|
||
def test_both_without_outputfile(self): | ||
"""Test script without -o option and 2 input files""" | ||
|
||
with temp_cwd(None): | ||
shutil.copy(data_dir / 'file1_fr_crlf.po', '.') | ||
shutil.copy(data_dir / 'file2_fr_lf.po', '.') | ||
assert_python_ok(msgfmt_py, 'file1_fr_crlf.po', 'file2_fr_lf.po') | ||
self.assertTrue(filecmp.cmp(data_dir / 'file1_fr_crlf.mo', | ||
'file1_fr_crlf.mo')) | ||
self.assertTrue(filecmp.cmp(data_dir / 'file2_fr_lf.mo', | ||
'file2_fr_lf.mo')) | ||
|
||
|
||
class PONamesTest(unittest.TestCase): | ||
def test_no_extension(self): | ||
with temp_cwd(None): | ||
shutil.copy(data_dir / 'file1_fr_crlf.po', 'file1.fr.po') | ||
assert_python_ok(msgfmt_py, 'file1.fr') | ||
self.assertTrue(os.path.exists('file1.fr.mo')) | ||
|
||
def test_wrong_extension(self): | ||
with temp_cwd(None): | ||
shutil.copy(data_dir / 'file1_fr_crlf.po', 'file1_fr.pox') | ||
assert_python_failure(msgfmt_py, 'file1_fr.pox') | ||
self.assertFalse(os.path.exists('file1_fr.mo')) | ||
self.assertFalse(os.path.exists('file1_fr.pox.mo')) | ||
|
||
@unittest.skipUnless(sys.platform.startswith("win"), "uppercase on Windows") | ||
def test_MAJ_on_Windows(self): | ||
with temp_cwd(None): | ||
shutil.copy(data_dir / 'file1_fr_crlf.po', 'File1.PO') | ||
assert_python_ok(msgfmt_py, 'FIle1.Po') | ||
self.assertTrue(os.path.exists('file1.mo')) | ||
|
||
|
||
def make_message_files(mo_file, *po_files): | ||
compile_many_messages(mo_file, *po_files) | ||
# Create a human-readable JSON file which is | ||
# easier to review than the binary .mo file. | ||
with open(mo_file, 'rb') as f: | ||
translations = GNUTranslations(f) | ||
catalog_file = mo_file.with_suffix('.json') | ||
with open(catalog_file, 'w') as f: | ||
data = translations._catalog.items() | ||
data = sorted(data, key=lambda x: (isinstance(x[0], tuple), x[0])) | ||
json.dump(data, f, indent=4) | ||
f.write('\n') | ||
|
||
|
||
def update_catalog_snapshots(): | ||
for po_file in data_dir.glob('*.po'): | ||
mo_file = po_file.with_suffix('.mo') | ||
compile_messages(po_file, mo_file) | ||
# Create a human-readable JSON file which is | ||
# easier to review than the binary .mo file. | ||
with open(mo_file, 'rb') as f: | ||
translations = GNUTranslations(f) | ||
catalog_file = po_file.with_suffix('.json') | ||
with open(catalog_file, 'w') as f: | ||
data = translations._catalog.items() | ||
data = sorted(data, key=lambda x: (isinstance(x[0], tuple), x[0])) | ||
json.dump(data, f, indent=4) | ||
f.write('\n') | ||
make_message_files(mo_file, po_file) | ||
# special processing for file12_fr.mo which results from 2 input files | ||
make_message_files(data_dir / 'file12_fr.mo', | ||
data_dir / 'file1_fr_crlf.po', | ||
data_dir / 'file2_fr_lf.po') | ||
|
||
|
||
if __name__ == '__main__': | ||
|
2 changes: 2 additions & 0 deletions
2
Misc/NEWS.d/next/Tools-Demos/2018-12-05-20-46-10.bpo-35335.qtIUBx.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
:program:`msgfmt.py` is now able to merge more than one po file into a compiled mo | ||
file. When an entry exists in more than on input file, the last file wins. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.