i18n: show current product name in i18n strings for Python code

Summary: Makes internationalization strings (i.e. those that start with `_()` to use the Default identity, which is mainly based on the name of the current binary. These strings are used in a bunch of places for help text.

Differential Revision: D40157345

fbshipit-source-id: c70ee9ece543c2ef0285f8b1a16e2f48f54e424e
This commit is contained in:
Saul Gutierrez 2022-10-10 16:39:36 -07:00 committed by Facebook GitHub Bot
parent 7ad904d0cf
commit 6b46daf35b
5 changed files with 51 additions and 19 deletions

View File

@ -427,9 +427,9 @@ class _helpdispatch(object):
if entry[2].startswith("hg"):
rst.append("%s\n" % entry[2])
else:
rst.append("%s %s %s\n" % (identity.prog, cmd, entry[2]))
rst.append("%s %s %s\n" % (identity.default().cliname(), cmd, entry[2]))
else:
rst.append("%s %s\n" % (identity.prog, cmd))
rst.append("%s %s\n" % (identity.default().cliname(), cmd))
# aliases
# try to simplify aliases, ex. compress ['ab', 'abc', 'abcd', 'abcde']
# to ['ab', 'abcde']

View File

@ -14,21 +14,25 @@ import functools
from bindings import identity
prog = "hg"
product = "Mercurial"
longproduct = "Mercurial Distributed SCM"
templatemap = {"@prog@": prog, "@Product@": product, "@LongProduct@": longproduct}
sniffroot = identity.sniffroot
sniffenv = identity.sniffenv
current = identity.current
default = identity.default
def templatemap():
currident = default()
return {
"@prog@": currident.cliname(),
"@Product@": currident.productname(),
"@LongProduct@": currident.longproductname(),
}
def replace(s):
"""Replace template instances in the given string"""
if s is not None:
for template, replacement in templatemap.items():
for template, replacement in templatemap().items():
s = s.replace(template, replacement)
return s

View File

@ -410,18 +410,19 @@ def inlineliterals(blocks):
def hgrole(blocks):
unisubst = list(identity.templatemap().items())
substs = [
(":hg:`", "'%s " % identity.prog),
(":prog:`", "'%s " % identity.prog),
(":hg:`", "'%s " % identity.default().cliname()),
(":prog:`", "'%s " % identity.default().cliname()),
("`", "'"),
]
] + unisubst
for b in blocks:
if b["type"] in ("paragraph", "section"):
# Turn :hg:`command` into "hg command". This also works
# when there is a line break in the command and relies on
# the fact that we have no stray back-quotes in the input
# (run the blocks through inlineliterals first).
b["lines"] = [replace(l, substs) for l in b["lines"]]
stype = substs if b["type"] in ("paragraph", "section") else unisubst
# Turn :hg:`command` into "hg command". This also works
# when there is a line break in the command and relies on
# the fact that we have no stray back-quotes in the input
# (run the blocks through inlineliterals first).
b["lines"] = [replace(l, stype) for l in b["lines"]]
return blocks

View File

@ -21,6 +21,7 @@ pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
m.add_class::<identity>(py)?;
m.add(py, "all", py_fn!(py, all()))?;
m.add(py, "current", py_fn!(py, current()))?;
m.add(py, "default", py_fn!(py, default()))?;
m.add(py, "sniffenv", py_fn!(py, sniff_env()))?;
m.add(py, "sniffroot", py_fn!(py, sniff_root(path: PyPathBuf)))?;
m.add(py, "sniffdir", py_fn!(py, sniff_dir(path: PyPathBuf)))?;
@ -40,6 +41,10 @@ py_class!(pub class identity |py| {
Ok(format!("{}", self.ident(py)))
}
def cliname(&self) -> PyResult<String> {
Ok(self.ident(py).cli_name().to_string())
}
def configrepofile(&self) -> PyResult<String> {
Ok(self.ident(py).config_repo_file().to_string())
}
@ -47,6 +52,14 @@ py_class!(pub class identity |py| {
def userconfigpaths(&self) -> PyResult<Vec<PyPathBuf>> {
self.ident(py).user_config_paths().iter().map(|p| p.as_path().try_into()).collect::<Result<Vec<PyPathBuf>>>().map_pyerr(py)
}
def productname(&self) -> PyResult<String> {
Ok(self.ident(py).product_name().to_string())
}
def longproductname(&self) -> PyResult<String> {
Ok(self.ident(py).long_product_name().to_string())
}
});
fn sniff_env(py: Python) -> PyResult<identity> {
@ -80,6 +93,10 @@ fn current(py: Python) -> PyResult<identity> {
identity::create_instance(py, rsident::IDENTITY.read().clone())
}
fn default(py: Python) -> PyResult<identity> {
identity::create_instance(py, rsident::idents::DEFAULT.clone())
}
fn all(py: Python) -> PyResult<Vec<identity>> {
rsident::idents::ALL_IDENTITIES
.iter()

View File

@ -25,9 +25,12 @@ pub struct Identity {
/// Example: `Checkout failed. Resume with 'sl checkout --continue'`
cli_name: &'static str,
/// Full name of the product
/// Name of the product
product_name: &'static str,
/// Full name of the product
long_product_name: &'static str,
/// Metadata directory of the current identity. If this directory exists in the current repo, it
/// implies that the repo is using this identity.
dot_dir: &'static str,
@ -79,6 +82,10 @@ impl Identity {
self.product_name
}
pub fn long_product_name(&self) -> &'static str {
self.long_product_name
}
pub fn dot_dir(&self) -> &'static str {
self.dot_dir
}
@ -162,6 +169,7 @@ impl std::fmt::Display for Identity {
const HG: Identity = Identity {
cli_name: "hg",
product_name: "Mercurial",
long_product_name: "Mercurial Distributed SCM",
dot_dir: ".hg",
env_prefix: "HG",
config_name: "hgrc",
@ -176,6 +184,7 @@ const HG: Identity = Identity {
const SL: Identity = Identity {
cli_name: "sl",
product_name: "Sapling",
long_product_name: "Sapling SCM",
dot_dir: ".sl",
env_prefix: "SL",
config_name: "slconfig",
@ -191,6 +200,7 @@ const SL: Identity = Identity {
const TEST: Identity = Identity {
cli_name: "test",
product_name: "Test",
long_product_name: "Testing SCM",
dot_dir: ".test",
env_prefix: "TEST",
config_name: "testrc",