зеркало из https://github.com/microsoft/azure-cli.git
Replaces gettext loc with custom
Adds tool to extract strings Allows config file to specify locale
This commit is contained in:
Родитель
1146a74c7e
Коммит
d014e9b38b
|
@ -9,7 +9,6 @@ env/
|
|||
.ptvs/
|
||||
|
||||
# Build results
|
||||
bin/
|
||||
obj/
|
||||
dist/
|
||||
MANIFEST
|
||||
|
|
62
.hgignore
62
.hgignore
|
@ -1,62 +0,0 @@
|
|||
syntax: glob
|
||||
# Python cache
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Virtual environment
|
||||
env/
|
||||
|
||||
# PTVS analysis
|
||||
.ptvs/
|
||||
|
||||
# Build results
|
||||
bin/
|
||||
obj/
|
||||
dist/
|
||||
MANIFEST
|
||||
|
||||
# Result of running python setup.py install/pip install -e
|
||||
RECORD.txt
|
||||
build/
|
||||
*.egg-info/
|
||||
|
||||
# Test results
|
||||
TestResults/
|
||||
|
||||
# Credentials
|
||||
credentials_real.json
|
||||
testsettings_local.json
|
||||
servicebus_settings_real.py
|
||||
storage_settings_real.py
|
||||
legacy_mgmt_settings_real.py
|
||||
mgmt_settings_real.py
|
||||
app_creds_real.py
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
.vs/
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
||||
|
||||
.idea
|
||||
src/build
|
||||
*.iml
|
||||
/doc/_build
|
||||
/.vs/config/applicationhost.config
|
||||
|
||||
# Azure deployment credentials
|
||||
*.pubxml
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent / "src" / "azure" / "cli"
|
||||
OUTPUT = ROOT / "locale" / "en-US" / "messages.txt"
|
||||
|
||||
print('Extracting from:', ROOT)
|
||||
|
||||
if not ROOT.is_dir():
|
||||
print("Failed to locate 'azure/cli'")
|
||||
sys.exit(1)
|
||||
|
||||
if not OUTPUT.parent.is_dir():
|
||||
os.makedirs(str(OUTPUT.parent))
|
||||
|
||||
with open(str(OUTPUT), 'w', encoding='utf-8-sig') as f_out:
|
||||
for path in ROOT.rglob('*.py'):
|
||||
with open(str(path), 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
for m in re.finditer('[^\w_]_\(("(.+)"|\'(.+)\')\)', content):
|
||||
print('# From', path, ':', m.span()[0], file=f_out)
|
||||
print('KEY:', m.group(2) or m.group(3), file=f_out)
|
||||
print(m.group(2) or m.group(3), file=f_out)
|
||||
print(file=f_out)
|
|
@ -3,6 +3,7 @@ import json
|
|||
import os
|
||||
import sys
|
||||
|
||||
from ._locale import get_file as locale_get_file
|
||||
from ._logging import logging
|
||||
|
||||
# Named arguments are prefixed with one of these strings
|
||||
|
@ -63,15 +64,12 @@ class ArgumentParser(object):
|
|||
def __init__(self, prog):
|
||||
self.prog = prog
|
||||
self.noun_map = {
|
||||
'$doc': 'azure-cli',
|
||||
'$doc': 'azure-cli.txt',
|
||||
}
|
||||
self.help_args = { '--help', '-h' }
|
||||
self.complete_args = { '--complete' }
|
||||
self.global_args = { '--verbose', '--debug' }
|
||||
|
||||
self.doc_source = './'
|
||||
self.doc_suffix = '.txt'
|
||||
|
||||
def add_command(self, handler, name=None, description=None, args=None):
|
||||
'''Registers a command that may be parsed by this parser.
|
||||
|
||||
|
@ -98,7 +96,7 @@ class ArgumentParser(object):
|
|||
for n in nouns:
|
||||
full_name += n
|
||||
m = m.setdefault(n.lower(), {
|
||||
'$doc': full_name
|
||||
'$doc': full_name + ".txt"
|
||||
})
|
||||
full_name += '.'
|
||||
m['$description'] = description or handler.__doc__
|
||||
|
@ -234,7 +232,7 @@ class ArgumentParser(object):
|
|||
print(' {0:<{1}} - {2}'.format(a, maxlen, d), file=out)
|
||||
print(file=out, flush=True)
|
||||
|
||||
doc_file = os.path.join(self.doc_source, noun_map['$doc'] + self.doc_suffix)
|
||||
doc_file = locale_get_file(noun_map['$doc'])
|
||||
try:
|
||||
with open(doc_file, 'r') as f:
|
||||
print(f.read(), file=out, flush=True)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import os.path
|
||||
|
||||
from codecs import open
|
||||
|
||||
def install(locale_dir):
|
||||
mapping = []
|
||||
|
||||
with open(os.path.join(locale_dir, "messages.txt"), 'r', encoding='utf-8-sig') as f:
|
||||
for i in f:
|
||||
if not i or i.startswith('#') or not i.strip():
|
||||
continue
|
||||
if i.startswith('KEY: '):
|
||||
mapping.append((i[5:].strip(), None))
|
||||
else:
|
||||
mapping[-1] = (mapping[-1][0], i.strip())
|
||||
|
||||
translations = dict(mapping)
|
||||
def _(key):
|
||||
return translations.get(key) or '<NO_TRANSLATION:{}>'.format(key)
|
||||
_.locale_dir = locale_dir
|
||||
|
||||
__builtins__['_'] = _
|
||||
|
||||
def get_file(name):
|
||||
try:
|
||||
src = _.locale_dir
|
||||
except (NameError, AttributeError):
|
||||
raise RuntimeError("localizations not installed")
|
||||
|
||||
return os.path.join(src, name)
|
|
@ -1,6 +1,8 @@
|
|||
import logging as _logging
|
||||
import sys
|
||||
|
||||
__all__ = ['logging', 'configure_logging']
|
||||
|
||||
_CODE_LEVEL = _logging.INFO + 1
|
||||
|
||||
class Logger(_logging.Logger):
|
||||
|
@ -30,28 +32,26 @@ def _arg_name(arg):
|
|||
return a.lower()
|
||||
|
||||
def configure_logging(argv, config):
|
||||
# TODO: Configure logging handler to log messages to .py file
|
||||
# Thinking here:
|
||||
# INFO messages as Python code
|
||||
# DEBUG messages (if -v) as comments
|
||||
# WARNING/ERROR messages as clearly marked comments
|
||||
|
||||
# Currently we just use the default format
|
||||
level = _logging.WARNING
|
||||
|
||||
# Load logging info from config
|
||||
if config.get('verbose'):
|
||||
level = _logging.INFO
|
||||
if config.get('debug'):
|
||||
level = _logging.DEBUG
|
||||
logfile = config.get('log')
|
||||
|
||||
logfile = None
|
||||
# Load logging info from arguments
|
||||
# Also remove any arguments consumed so that the parser does not
|
||||
# have to explicitly ignore them.
|
||||
i = 0
|
||||
while i < len(argv):
|
||||
arg = _arg_name(argv[i])
|
||||
if arg in ('v', 'verbose'):
|
||||
level = _logging.INFO
|
||||
level = min(_logging.INFO, level)
|
||||
argv.pop(i)
|
||||
elif arg in ('debug',):
|
||||
level = _logging.DEBUG
|
||||
level = min(_logging.DEBUG, level)
|
||||
argv.pop(i)
|
||||
elif arg in ('log',):
|
||||
argv.pop(i)
|
||||
|
@ -61,20 +61,22 @@ def configure_logging(argv, config):
|
|||
pass
|
||||
else:
|
||||
i += 1
|
||||
logging.setLevel(_logging.INFO)
|
||||
|
||||
# Configure the console output handler
|
||||
stderr_handler = _logging.StreamHandler(sys.stderr)
|
||||
stderr_handler.formatter = _logging.Formatter('%(levelname)s: %(message)s')
|
||||
stderr_handler.level = level
|
||||
logging.level = stderr_handler.level = level
|
||||
logging.handlers.append(stderr_handler)
|
||||
|
||||
if logfile and logfile.lower().endswith('.py'):
|
||||
# Configure a handler that logs code to a Python script
|
||||
py_handler = _logging.StreamHandler(open(logfile, 'w', encoding='utf-8'))
|
||||
py_handler.formatter = PyFileFormatter()
|
||||
py_handler.level = level if level == _logging.DEBUG else _logging.INFO
|
||||
logging.handlers.append(py_handler)
|
||||
elif logfile:
|
||||
# Configure the handler that logs code to a text file
|
||||
log_handler = _logging.StreamHandler(open(logfile, 'w', encoding='utf-8'))
|
||||
log_handler.formatter = _logging.Formatter('[%(levelname)s:%(asctime)s] %(message)s')
|
||||
log_handler.level = level if level == _logging.DEBUG else _logging.INFO
|
||||
logging.handlers.append(log_handler)
|
||||
logging.handlers.append(log_handler)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# From D:\Repos\azure-cli\src\azure\cli\_argparse.py : 1208
|
||||
KEY: Argument {0} is required
|
||||
Argument {0} is required
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\_argparse.py : 6848
|
||||
KEY: argument '{0}' does not take a value
|
||||
argument '{0}' does not take a value
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1147
|
||||
KEY: user password or service principal secret, will prompt if not given.
|
||||
user password or service principal secret, will prompt if not given.
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1253
|
||||
KEY: If given, log in as a service principal rather than a user.
|
||||
If given, log in as a service principal rather than a user.
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1367
|
||||
KEY: A PEM encoded certificate private key file.
|
||||
A PEM encoded certificate private key file.
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1454
|
||||
KEY: A hex encoded thumbprint of the certificate.
|
||||
A hex encoded thumbprint of the certificate.
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1535
|
||||
KEY: Tenant domain or ID to log into.
|
||||
Tenant domain or ID to log into.
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1597
|
||||
KEY: do not prompt for confirmation of PII storage.
|
||||
do not prompt for confirmation of PII storage.
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 1927
|
||||
KEY: Unknown environment {0}
|
||||
Unknown environment {0}
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 2091
|
||||
KEY: Tenant:
|
||||
Tenant:
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 2381
|
||||
KEY: Password:
|
||||
Password:
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 2883
|
||||
KEY: No subscriptions found for this account
|
||||
No subscriptions found for this account
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\login.py : 2991
|
||||
KEY: Setting subscription %s as default
|
||||
Setting subscription %s as default
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\storage.py : 268
|
||||
KEY: the resource group name
|
||||
the resource group name
|
||||
|
||||
# From D:\Repos\azure-cli\src\azure\cli\commands\storage.py : 332
|
||||
KEY: the subscription id
|
||||
the subscription id
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
import gettext
|
||||
import os
|
||||
|
||||
gettext.install("az", os.path.join(os.path.abspath(__file__), '..', 'locale'))
|
||||
|
||||
from ._argparse import ArgumentParser
|
||||
from ._locale import install as locale_install
|
||||
from ._logging import configure_logging, logging
|
||||
from ._session import Session
|
||||
|
||||
|
@ -13,6 +11,11 @@ CONFIG = Session()
|
|||
# SESSION provides read-write session variables
|
||||
SESSION = Session()
|
||||
|
||||
# Load the user's preferred locale from their configuration
|
||||
LOCALE = CONFIG.get('locale', 'en-US')
|
||||
locale_install(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'locale', LOCALE))
|
||||
|
||||
|
||||
def main(args):
|
||||
CONFIG.load(os.path.expanduser('~/az.json'))
|
||||
SESSION.load(os.path.expanduser('~/az.sess'), max_age=3600)
|
||||
|
@ -22,9 +25,6 @@ def main(args):
|
|||
parser = ArgumentParser("az")
|
||||
|
||||
import azure.cli.commands as commands
|
||||
parser.doc_source = os.path.dirname(commands.__file__)
|
||||
# TODO: detect language
|
||||
parser.doc_suffix = '.en_US.txt'
|
||||
|
||||
# Find the first noun on the command line and only load commands from that
|
||||
# module to improve startup time.
|
||||
|
|
Загрузка…
Ссылка в новой задаче