[Bf-docboard-svn] bf-manual: [7414] trunk/blender_docs/tools_maintenance: po_shortcuts.py simplification
Pep
noreply at blender.org
Fri Nov 20 11:15:43 CET 2020
Revision: 7414
https://developer.blender.org/rBM7414
Author: pepribal
Date: 2020-11-20 11:15:43 +0100 (Fri, 20 Nov 2020)
Log Message:
-----------
po_shortcuts.py simplification
Added Paths:
-----------
trunk/blender_docs/tools_maintenance/po_shortcuts.py
trunk/blender_docs/tools_maintenance/po_shortcuts_tables.json
Removed Paths:
-------------
trunk/blender_docs/tools_maintenance/change_shortcuts/
Added: trunk/blender_docs/tools_maintenance/po_shortcuts.py
===================================================================
--- trunk/blender_docs/tools_maintenance/po_shortcuts.py (rev 0)
+++ trunk/blender_docs/tools_maintenance/po_shortcuts.py 2020-11-20 10:15:43 UTC (rev 7414)
@@ -0,0 +1,156 @@
+#! /usr/bin/env python3
+
+# Changes the shortcuts (:kbd:`...`) across all the translated PO files
+# of a spcecific language, according to the provided JSON table.
+# Language code and output directory must be provided.
+
+import json
+import sys
+import os
+import re
+
+ROLE = ':kbd:' # Change to any other role if needed
+
+
+def find_vcs_root(dirs=(".svn", ".git"), default=None):
+ """
+ Returns the repo root dir.
+
+ :param dirs: dirs to look for, for repo detection.
+ :param default: value to return if not found.
+ :return: repo root dir.
+ """
+ prev, test = None, os.path.abspath(os.path.dirname(__file__))
+ while prev != test:
+ if any(os.path.isdir(os.path.join(test, d)) for d in dirs):
+ return test
+ prev, test = test, os.path.abspath(os.path.join(test, os.pardir))
+ return default
+
+
+def msgstr_replace(msgstr):
+ """
+ Replaces and returns the provided string based on the substitution table.
+
+ Function attribute 'table' contains the substitution table, as a list of
+ 2-tuples with replacements for the language of the form
+ (regex object, replacement string).
+ :param msgstr: string to process.
+ :return: replaced string, number of changes made.
+ """
+ ntotal = 0
+ for regex, repl in msgstr_replace.table:
+ msgstr, n = regex.subn(repl, msgstr)
+ ntotal += n
+ return msgstr, ntotal
+
+
+def file_process(filename):
+ """
+ Processes the given file. If changes are made, output file is generated.
+
+ :param filename: the path and name of the file to process.
+ :return: nothing.
+ """
+ out_text = ''
+ n_changes = 0
+ with open(filename, 'rt') as f:
+ msgstr = ''
+ for line in f:
+ if msgstr:
+ if line.startswith('"'):
+ msgstr += line
+ else:
+ newtext, n = msgstr_replace(msgstr)
+ out_text += newtext + line
+ n_changes += n
+ msgstr = ''
+ else:
+ if line.startswith('msgstr'):
+ msgstr += line
+ else:
+ out_text += line
+ if msgstr: # is there a last pending msgstr?
+ newtext, n = msgstr_replace(msgstr)
+ out_text += newtext
+ n_changes += n
+ # In case there were changes, an output file is generated:
+ if n_changes > 0:
+ print(filename[filename.find('LC_MESSAGES')+11:] + ':',
+ n_changes, 'change(s).')
+ file_out = os.path.join(os.path.expanduser(sys.argv[2]),
+ 'new_' + filename[filename.find('locale'):])
+ os.makedirs(os.path.dirname(file_out), exist_ok=True)
+ with open(file_out, 'wt') as f:
+ f.write(out_text)
+
+
+def json_parse(obj):
+ """
+ Function used to parse the json file.
+
+ :param obj: tuple passed by 'json.load()'.
+ :return: if 'obj' is top level, it returns the table in a list of 2-tuples,
+ or None if table not found, or duplicate elements present.
+ If not on top level, it just returns the passed object.
+ """
+ retval = obj
+ if isinstance(obj[0][1], list): # top level?
+ retval = None # language table not found so far
+ for tpl in obj:
+ if tpl[0] == sys.argv[1]: # table found?
+ retval = tpl[1]
+ break
+ if retval: # table was found?
+ # Let's check for duplicates:
+ test_set = set(retval)
+ if len(test_set) < len(retval): # duplicates?
+ print(f"Error: '{sys.argv[1]}' table contains duplicate entries.")
+ retval = None
+ else:
+ print(f"Error: '{sys.argv[1]}' table not found.")
+ return retval
+
+
+root_path = find_vcs_root()
+
+# Preliminary checks:
+if root_path is None:
+ print('Repository not found. Script must be in a repo subfolder.')
+elif len(sys.argv) != 3:
+ print("""\nUsage: po_shortcuts.py <LANGUAGE> <FOLDER>\n
+ Examples: po_shortcuts.py es ~/test
+ po_shortcuts.py fr d:\\test\n
+ Substitution table needed in 'po_shortcuts_tables.json'.
+ Script and tables file must be in the same folder.\n
+ Output files will be created in 'new_locale' subfolder
+ inside the provided folder in your computer.""")
+elif not os.path.isdir(os.path.join(root_path, 'locale', sys.argv[1])):
+ print("'<repo_root>/locale/" + sys.argv[1] + "' folder not found. "
+ "Script must be in a folder inside the repository.")
+elif not os.path.isfile('po_shortcuts_tables.json'):
+ print("'po_shortcuts_tables.json' file not found. "
+ "Script and tables file must be in the same folder.")
+elif not os.path.isdir(os.path.expanduser(sys.argv[2])):
+ print("'" + sys.argv[2] + "' folder not found.")
+else: # All OK
+ # Reading substitution table. It will be stored as a list of tuples
+ # (regex object, replace string) in function attribute 'table' of
+ # msgstr_replace() function:
+ with open('po_shortcuts_tables.json', 'rt') as ftab:
+ table = json.load(ftab, object_pairs_hook=json_parse)
+ if table: # table found and no duplicates?
+ msgstr_replace.table = []
+ for src, dst in table:
+ pattern = r'(' + ROLE + r')("\n")?(`.*?)\b' + src + r'\b(.*?`)'
+ replace = r'\1\2\3' + dst + r'\4'
+ msgstr_replace.table.append((re.compile(pattern, re.MULTILINE),
+ replace))
+ # Main loop:
+ for wpath, wdirs, wfiles in os.walk(os.path.join(root_path, 'locale',
+ sys.argv[1],
+ 'LC_MESSAGES')):
+ for fname in wfiles:
+ path_full = os.path.join(wpath, fname)
+ if path_full[-3:] == '.po':
+ file_process(path_full)
Property changes on: trunk/blender_docs/tools_maintenance/po_shortcuts.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/blender_docs/tools_maintenance/po_shortcuts_tables.json
===================================================================
--- trunk/blender_docs/tools_maintenance/po_shortcuts_tables.json (rev 0)
+++ trunk/blender_docs/tools_maintenance/po_shortcuts_tables.json 2020-11-20 10:15:43 UTC (rev 7414)
@@ -0,0 +1,53 @@
+{
+ "es": {
+ "Left": "Izquierda",
+ "Right": "Derecha",
+ "Up": "Arriba",
+ "Down": "Abajo",
+ "Return": "Intro",
+ "Comma": "Coma",
+ "Period": "Punto",
+ "BackSlash": "BarraInvertida",
+ "Slash": "Barra",
+ "Numpad0": "Num0",
+ "Numpad1": "Num1",
+ "Numpad2": "Num2",
+ "Numpad3": "Num3",
+ "Numpad4": "Num4",
+ "Numpad5": "Num5",
+ "Numpad6": "Num6",
+ "Numpad7": "Num7",
+ "Numpad8": "Num8",
+ "Numpad9": "Num9",
+ "Numpad": "Num",
+ "NumpadReturn": "NumIntro",
+ "NumpadPlus": "NumMás",
+ "NumpadMinus": "NumMenos",
+ "NumpadSlash": "NumBarra",
+ "NumpadPeriod": "NumPunto",
+ "AccentGrave": "AcentoGrave",
+ "Backspace": "Retroceso",
+ "Delete": "Supr",
+ "Home": "Inicio",
+ "End": "Fin",
+ "PgUp": "RePág",
+ "PgDn": "AvPág",
+ "PageUp": "RePág",
+ "PageDn": "AvPág",
+ "Shift": "Mays",
+ "WheelUp": "RuedaArriba",
+ "WheelDown": "RuedaAbajo",
+ "Wheel": "Rueda",
+ "Spacebar": "Espacio",
+ "LMB": "RatónIzq",
+ "RMB": "RatónDer",
+ "MMB": "RatónMed"
+ },
+
+ "fr": {
+ "Left": "Gauche",
+ "Right": "Droite",
+ "Up": "Haut",
+ "Down": "Bas"
+ }
+}
\ No newline at end of file
Property changes on: trunk/blender_docs/tools_maintenance/po_shortcuts_tables.json
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
More information about the Bf-docboard-svn
mailing list