
    Pmj)                       U d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddl
mZ  ej        e          ZdZded	<   d
Zi dd
dd
dd
ddddddddddddddddddddddddddddi d dd!dd"dd#dd$d%d&d%d'd%d(d%d)d%d*d%d+d,d-d,d.d,d/d,d0d,d1d,d2d,i d3d4d5d4d6d4d7d4d8d4d9d:d;d:d<d:d=d>d?d>d@dAdBdAdCdAdDdEdFdEdGdEdHdEi dIdJdKdJdLdJdMdNdOdNdPdNdQdNdRdNdSdNdTdNdUdVdWdVdXdVdYdZd[dZd\dZd]d^d^d^d^d^d^d^d_Zd`eda<   i Zdbedc<    ej                    Zd|dfZd}djZd~dlZddqZ edrs          ddu            ZddvZddwZdddzZg d{ZdS )a@  Lightweight internationalization (i18n) for Hermes static user-facing messages.

Scope (thin slice, by design): only the highest-impact static strings shown
to the user by Hermes itself -- approval prompts, a handful of gateway slash
command replies, restart-drain notices.  Agent-generated output, log lines,
error tracebacks, tool outputs, and slash-command descriptions all stay in
English.

Catalog files live under ``locales/<lang>.yaml`` at the repo root.  Each
catalog is a flat dict keyed by dotted paths (e.g. ``approval.choose`` or
``gateway.approval_expired``).  Missing keys fall back to English; if English
is missing too, the key path itself is returned so a broken catalog never
crashes the agent.

Usage::

    from agent.i18n import t
    print(t("approval.choose_long"))                       # current lang
    print(t("gateway.draining", count=3))                  # {count} formatted
    print(t("approval.choose_long", lang="zh"))            # explicit override

Language resolution order:
    1. Explicit ``lang=`` argument passed to :func:`t`
    2. ``HERMES_LANGUAGE`` environment variable (for tests / quick override)
    3. ``display.language`` from config.yaml
    4. ``"en"`` (baseline)

Supported languages: en, zh, zh-hant, ja, de, es, fr, tr, uk, af, ko, it, ga,
pt, ru, hu, ar.  Unknown values fall back to en.
    )annotationsN)	lru_cache)Path)Any)enzhzh-hantjadeesfrtrukafkoitgaptruhuarztuple[str, ...]SUPPORTED_LANGUAGESr   englishzen-uszen-gbchineser   mandarinzzh-cnzzh-hanszzh-sgztraditional-chineser	   traditional_chinesezzh-twzzh-hkzzh-mojapaneser
   jpzja-jpgermanr   deutschzde-dezde-atzde-chspanishr   u   españolespanolzes-eszes-mxzes-arfrenchr   u	   françaisfrancezfr-frzfr-bezfr-cazfr-ch	ukrainianr   
ukrainischu   українськаzuk-uauaturkishr   u   türkçeztr-tr	afrikaansr   zaf-zakoreanr   u	   한국어zko-kritalianr   italianozit-itzit-chirishr   gaeilgezga-ie
portugueser   u
   português	portugueszpt-ptzpt-br	brazilian
brasileirorussianr   u   русскийzru-ru	hungarianr   magyarzhu-huarabicr   )u   العربيةzar-sazar-egzar-aezar-mazar-dzdict[str, str]_LANGUAGE_ALIASESzdict[str, dict[str, str]]_catalog_cachereturnr   c                 >   t          j        dd                                          } | r@t          |           }|                                r|S t
                              d|            t          t                                                    j	        j	        dz  }|S )a4  Return the directory containing locale YAML files.

    Resolution order, first existing wins:

    1. ``HERMES_BUNDLED_LOCALES`` env var -- set by the Nix wrapper (or any
       sealed-packaging system) to point at the installed catalog directory.
    2. ``<repo-root>/locales`` -- source checkouts and editable installs,
       where the working tree sits next to ``agent/``.

    Falling through to the source-style path (even when missing) keeps
    ``_load_catalog`` error messages informative -- it logs the path it
    looked at -- rather than raising.
    HERMES_BUNDLED_LOCALES zlHERMES_BUNDLED_LOCALES points to a non-directory path (%s); falling back to bundled/source locale resolutionlocales)
osgetenvstripr   is_dirloggerwarning__file__resolveparent)override	candidate
source_dirs      0/home/thesage/.hermes/hermes-agent/agent/i18n.py_locales_dirrL   [   s     y1266<<>>H 
NN	 	?	
 	
 	
 h''))07)CJ    valuer   strc                6   t          | t                    st          S |                                                                 }|st          S |t
          v r|S |t          v rt          |         S |                    dd          d         }|t
          v r|S t          S )a  Normalize a user-supplied language value to a supported code.

    Accepts supported codes directly, common aliases (``chinese`` -> ``zh``),
    and case-insensitive regional tags (``zh-CN`` -> ``zh``).  Returns the
    default language for unknown values.
    -   r   )
isinstancerO   DEFAULT_LANGUAGErA   lowerr   r8   split)rN   keybases      rK   _normalize_langrY   y   s     eS!!  
++--



C  
!!!

 %% 99S!QD"""rM   langc                D   t           5  t                              |           }||cddd           S 	 ddd           n# 1 swxY w Y   t                      |  dz  }|                                sGt
                              d| |           t           5  i t          | <   ddd           n# 1 swxY w Y   i S 	 ddl}|                    dd          5 }|	                    |          pi }ddd           n# 1 swxY w Y   n^# t          $ rQ}t
                              d||           t           5  i t          | <   ddd           n# 1 swxY w Y   i cY d}~S d}~ww xY wi }t          |d	|           t           5  |t          | <   ddd           n# 1 swxY w Y   |S )
zLoad and flatten one locale YAML file into a dotted-key dict.

    YAML files can be nested for human readability; this produces the flat
    key space :func:`t` expects.  Cached per-language for the process.
    Nz.yamlz!i18n catalog missing for %s at %sr   rzutf-8)encodingz"Failed to load i18n catalog %s: %sr=   )_catalog_lockr9   getrL   is_filerC   debugyamlopen	safe_load	ExceptionrD   _flatten_into)rZ   cachedpathrb   frawexcflats           rK   _load_catalogrm      s    
  ##D))                     
 >>tNNN*D<<>> 8$EEE 	& 	&#%N4 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&	YYsWY-- 	*..##)rC	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	*   ;T3GGG 	& 	&#%N4 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&							 D#r4   	 $ $#t$ $ $ $ $ $ $ $ $ $ $ $ $ $ $Ks   A  AAB--B14B1;D C:.D :C>>D C>D 
E!#E3E
>E
E	EE	EE!E!>FFFnodeprefixoutNonec                    t          | t                    rE|                                 D ].\  }}|r| d| nt          |          }t	          |||           /d S t          | t                    r| ||<   d S d S )N.)rS   dictitemsrO   rf   )rn   ro   rp   rW   rN   	child_keys         rK   rf   rf      s    $ **,, 	1 	1JC-3A6))C)))SI%C0000	1 	1 
D#		 F rM   rR   )maxsize
str | Nonec                    	 ddl m}   |             }|                    d          pi                     d          }|rt          |          S n2# t          $ r%}t
                              d|           Y d}~nd}~ww xY wdS )aC  Read ``display.language`` from config.yaml once per process.

    Cached because ``t()`` is called in hot paths (every approval prompt,
    every gateway reply) and re-reading YAML each call would be wasteful.
    ``reset_language_cache()`` clears this when config changes at runtime
    (e.g. after the setup wizard).
    r   )load_config_readonlydisplaylanguagez/Could not read display.language from config: %sN)hermes_cli.configrz   r_   rY   re   rC   ra   )rz   cfgrZ   rk   s       rK   _config_language_cachedr      s    M::::::""$$	""(b--j99 	)"4(((	) M M MFLLLLLLLLM4s   A
A 
A=A88A=c                     t                                            t          5  t                                           ddd           dS # 1 swxY w Y   dS )zInvalidate cached language resolution and catalogs.

    Call after :func:`hermes_cli.config.save_config` if a running process
    needs to pick up a changed ``display.language`` without restart.
    N)r   cache_clearr^   r9   clear rM   rK   reset_language_cacher      s     '')))	                   s   AAAc                     t           j                            d          } | rt          |           S t	                      }|r|S t
          S )z?Resolve the active language using env > config > default order.HERMES_LANGUAGE)r?   environr_   rY   r   rT   )env_langcfg_langs     rK   get_languager      sJ    z~~/00H )x(((&((H rM   rW   format_kwargsc                   |rt          |          nt                      }t          |          }|                    |           }|2|t          k    r't          t                                        |           }|t
                              d| |           | }|rR	  |j        di |S # t          t          t          f$ r*}t
                              d| |||           |cY d}~S d}~ww xY w|S )aA  Translate a dotted key to the active language.

    Parameters
    ----------
    key
        Dotted path into the catalog, e.g. ``"approval.choose_long"``.
    lang
        Explicit language override.  Takes precedence over env + config.
    **format_kwargs
        ``str.format`` substitution arguments (``t("gateway.drain", count=3)``
        expects a catalog entry with a ``{count}`` placeholder).

    Returns
    -------
    The translated string, or the English fallback if the key is missing in
    the target language, or the bare key if English is also missing.
    Nzi18n miss: key=%r lang=%rz3i18n format failed for key=%r lang=%r kwargs=%r: %sr   )rY   r   rm   r_   rT   rC   ra   formatKeyError
IndexError
ValueErrorrD   )rW   rZ   r   targetcatalogrN   rk   s          rK   tr      s   $ '+>_T"""FF##GKKE}#333.//33C88} 	0#v>>> 	5<00-000*j1 	 	 	NNEV]C   LLLLLL	 Ls   B( (C)?C$C)$C))r   rT   r   r   r   )r:   r   )rN   r   r:   rO   )rZ   rO   r:   r7   )rn   r   ro   rO   rp   r7   r:   rq   )r:   rx   )r:   rq   )r:   rO   )N)rW   rO   rZ   rx   r   r   r:   rO   )__doc__
__future__r   loggingr?   	threading	functoolsr   pathlibr   typingr   	getLogger__name__rC   r   __annotations__rT   r8   r9   Lockr^   rL   rY   rm   rf   r   r   r   r   __all__r   rM   rK   <module>r      sO    > # " " " " "  				                      		8	$	$(       "%t"%d"%$+T"% t	"%  	"% (/	"% 7@	"% HOPT	"% 9"% '<Y"% Y"%  "% -4Y"% "% D"% #*4"% d"% "% t"% &-d"% 5<T"% DKD"% t"%  "% (1$"% 9@"% HOPT"% W^_c"% d"%  "% (0"% 8?"% GNt"% V]^b"% elmq"% "% "% "% $T"% ,B4"% JQRV"% Y]^b"% t"%  "% (/"%  !"%  !"%$ d%"%$  %"%$ (/%"%( t)"%(  )"%( (/)"%( 7>t)"% "% "%, T-"%, d-"%, %,T-"%2 $3"%2 %d3"%2 -83"%4 T5"%4 D5"%4 #.t5"%4 6B45"%8 t9"%8 &t9"%8 .5d9"%< ="%<  ="%< (/="%@ dA"% "%@ '+D4$C"% "% "%  " " " "H -/ . . . .	     <   0       F    1   &      ) ) ) ) )X  rM   