forked from balisujohn/localwriter
-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathi18n.py
More file actions
112 lines (86 loc) · 4.2 KB
/
Copy pathi18n.py
File metadata and controls
112 lines (86 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# WriterAgent - AI Writing Assistant for LibreOffice
# Copyright (c) 2026 KeithCu (modifications and relicensing)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Internationalization (i18n) utility for WriterAgent.
Uses standard Python gettext to localize strings dynamically.
"""
import os
import gettext
import logging
from typing import Any, Optional, cast
from plugin.framework.constants import get_locales_dir
log = logging.getLogger("writeragent.i18n")
# Set by init_i18n(); always non-None after init_i18n() returns.
_translation: Optional[gettext.NullTranslations] = None
# LO UI locale tag used for the loaded catalog (for fluff-word cache keys).
_active_locale: str = "en_US"
# When UNO cannot supply ooLocale (tests, early init), use English catalogs.
_DEFAULT_LOCALE = "en_US"
def get_active_locale() -> str:
"""Return the locale tag for the gettext catalog loaded by init_i18n()."""
return _active_locale
def get_lo_locale(ctx=None):
"""Return the LibreOffice UI locale from configuration only (no OS LANG).
Reads ``/org.openoffice.Setup/L10N`` → ``ooLocale``. On failure or empty
value, returns ``en_US`` so gettext still loads a predictable catalog.
"""
try:
import uno
if ctx is None:
ctx = uno.getComponentContext()
smgr = cast("Any", ctx).getServiceManager()
config_provider = smgr.createInstanceWithContext("com.sun.star.configuration.ConfigurationProvider", ctx)
ca = config_provider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", (uno.createUnoStruct("com.sun.star.beans.PropertyValue", Name="nodepath", Value="/org.openoffice.Setup/L10N"),))
locale = ca.getPropertyValue("ooLocale")
if locale:
if "Mock" in str(type(locale)):
return _DEFAULT_LOCALE
# LibreOffice often returns "en-US", gettext prefers "en_US"
return locale.replace("-", "_")
except Exception as e:
log.debug("Failed to determine LibreOffice locale: %s", e)
return _DEFAULT_LOCALE
def init_i18n(ctx=None) -> None:
"""Load gettext for the current locale.
Always sets :data:`_translation` before return (``NullTranslations`` on any
failure so callers never see ``None`` after a successful call).
"""
global _translation, _active_locale
if _translation is not None:
return
try:
locale = get_lo_locale(ctx)
_active_locale = locale
locales_dir = get_locales_dir()
mofiles = gettext.find("writeragent", localedir=locales_dir, languages=[locale], all=True)
if not mofiles:
mofiles = []
log.debug("i18n init: ctx_is_none=%s locale=%s locales_dir=%s (exists=%s) mofiles=%s", ctx is None, locale, locales_dir, os.path.isdir(locales_dir), mofiles if mofiles else "none")
_translation = gettext.translation(domain="writeragent", localedir=locales_dir, languages=[locale], fallback=True)
log.debug("i18n init: translation_type=%s", type(_translation).__name__)
except Exception as e:
log.debug("Failed to initialize i18n: %s. Falling back to default gettext.", e)
_active_locale = _DEFAULT_LOCALE
_translation = gettext.NullTranslations()
log.debug("i18n init: translation_type=%s", type(_translation).__name__)
def _(message: str) -> str:
"""Translate English msgid *message* via gettext. Must be :class:`str`."""
if not isinstance(message, str):
raise TypeError("gettext msgid must be str")
global _translation
if _translation is None:
init_i18n()
assert _translation is not None
return _translation.gettext(message)