
    PL
jb%                       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Zd]ed^<   i Zd_ed`<    ej                    ZdydcZdzdgZd{diZd|dnZ edop          d}dr            Zd~dsZddtZdddwZg dx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, ja, de, es, fr, tr, uk.  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huz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dict[str, str]_LANGUAGE_ALIASESzdict[str, dict[str, str]]_catalog_cachereturnr   c                 h    t          t                                                    j        j        dz  S )zReturn the directory containing locale YAML files.

    Lives next to the repo root so both the bundled install and editable
    checkouts find it without PYTHONPATH gymnastics.
    locales)r   __file__resolveparent     ./home/kuhnn/.hermes/hermes-agent/agent/i18n.py_locales_dirrA   W   s'     >>!!##*1I==r?   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   )
isinstancerC   DEFAULT_LANGUAGEstriplowerr   r6   split)rB   keybases      r@   _normalize_langrN   a   s     eS!!  
++--



C  
!!!

 %% 99S!QD"""r?   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: %s )_catalog_lockr7   getrA   is_fileloggerdebugyamlopen	safe_load	Exceptionwarning_flatten_into)rO   cachedpathrY   frawexcflats           r@   _load_catalogre   y   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.)rG   dictitemsrC   r^   )rf   rg   rh   rL   rB   	child_keys         r@   r^   r^      s    $ **,, 	1 	1JC-3A6))C)))SI%C0000	1 	1 
D#		 F r?   rF   )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displaylanguagez/Could not read display.language from config: %sN)hermes_cli.configrr   rU   rN   r\   rW   rX   )rr   cfgrO   rc   s       r@   _config_language_cachedrw      s    M111111kmm	""(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)rw   cache_clearrT   r7   clearr>   r?   r@   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)osenvironrU   rN   rw   rH   )env_langcfg_langs     r@   get_languager      sJ    z~~/00H )x(((&((H r?   rL   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>   )rN   r   re   rU   rH   rW   rX   formatKeyError
IndexError
ValueErrorr]   )rL   rO   r   targetcatalogrB   rc   s          r@   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   rH   r   r   r{   )r8   r   )rB   r   r8   rC   )rO   rC   r8   r5   )rf   r   rg   rC   rh   r5   r8   ri   )r8   rp   )r8   ri   )r8   rC   )N)rL   rC   rO   rp   r   r   r8   rC   )__doc__
__future__r   loggingr~   	threading	functoolsr   pathlibr   typingr   	getLogger__name__rW   r   __annotations__rH   r6   r7   LockrT   rA   rN   re   r^   rw   r{   r   r   __all__r>   r?   r@   <module>r      s     < # " " " " "  				                      		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%< =%<  =%< (/=% %     B -/ . . . .	  > > > >   0       F    1   &      ) ) ) ) )X  r?   