§
    ÷žyjœ)  ã                  óä  — 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dr¬s¦  «        d€du„¦   «         Zd�dv„Zd‚dw„Zdƒd„dz„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/ragecks/.hermes/hermes-agent/agent/i18n.pyÚ_locales_dirrL   [   s—   € õ ŒyÐ1°2Ñ6Ô6×<Ò<Ñ>Ô>€HØð 
Ý˜‘N”Nˆ	Ø×ÒÑÔð 	ØÐÝ�Šð?àñ	
ô 	
ð 	
õ •h‘”×'Ò'Ñ)Ô)Ô0Ô7¸)ÑC€JØÐó    Ú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œ   € õ �e�SÑ!Ô!ð  ÝÐØ
�+Š+‰-Œ-×
Ò
Ñ
Ô
€CØð  ÝÐØ
Õ!Ð!Ð!Øˆ
Ø
ÕÐÐÝ  Ô%Ð%ð �9Š9�S˜!ÑÔ˜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 )
zÕLoad 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Ñ)Ô)ˆØÐØðð ð ð ñ ô ð ð àðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð õ
 ‰>Œ>˜t˜N˜N˜NÑ*€DØ�<Š<‰>Œ>ð Ý�ŠÐ8¸$ÀÑEÔEÐEÝð 	&ð 	&Ø#%�N˜4Ñ ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&àˆ	ðØˆˆˆØ�YŠY�s WˆYÑ-Ô-ð 	*°Ø—.’. Ñ#Ô#Ð) rˆCð	*ð 	*ð 	*ñ 	*ô 	*ð 	*ð 	*ð 	*ð 	*ð 	*ð 	*øøøð 	*ð 	*ð 	*ð 	*øøåð ð ð Ý�ŠÐ;¸TÀ3ÑGÔGÐGÝð 	&ð 	&Ø#%�N˜4Ñ ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&àˆ	ˆ	ˆ	ˆ	ˆ	ˆ	øøøøð	øøøð €DÝ�#�r˜4Ñ Ô Ð Ý	ð $ð $Ø#��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ð 	1‰JˆC�Ø-3ÐA˜6Ð)Ð) 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 )zÈInvalidate 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Ô0€HØð )Ý˜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Ø�KŠK˜ÑÔ€Eà€}˜Õ#3Ò3Ð3åÕ.Ñ/Ô/×3Ò3°CÑ8Ô8ˆà€}õ 	�ŠÐ0°#°vÑ>Ô>Ð>Øˆàð ð	Ø�5”<Ð0Ð0 -Ð0Ð0Ð0øÝ�*¥jÐ1ð 	ð 	ð 	Ý�NŠNØEØ�V˜]¨Cñô ð ð ˆLˆLˆLˆLˆLˆLøøøøð	øøøð €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ð"%ð   ð"%ð -4°Yð"%ð �ð"%ð ˜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 % dð3"%ð2 -8¸ð3"%ð4 ˆTð5"%ð4 ˜Dð5"%ð4 #.¨tð5"%ð4 6BÀ4ð5"%ð8 ˆtð9"%ð8 & tð9"%ð8 .5°dð9"%ð< �ð="%ð<   ð="%ð< (/°ð="%ð@ ˆdðA"%ð "%ð@ '+Ø˜D¨4¸$ÈðC"%ð "%ð "%Ð ð "ð "ð "ñ "ðH -/€Ð .Ð .Ð .Ñ .Ø�	”Ñ Ô €ðð ð ð ð<ð ð ð ð0 ð  ð  ð  ðFð ð ð ð €�1ÐÑÔðð ð ñ Ôðð&ð ð ð ðð ð ð ð)ð )ð )ð )ð )ðXð ð €€€rM   