{"id":9425,"library":"zope-i18n","title":"Zope Internationalization Support","description":"zope.i18n implements several APIs related to internationalization and localization, offering features such as locale objects based on ICU, Gettext-based message catalogs, and locale discovery for web requests. Version 6.0, released recently, continues its active development with regular updates to support new Python versions and address architectural improvements.","status":"active","version":"6.0","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/zope.i18n","tags":["i18n","localization","internationalization","gettext","zope","plone"],"install":[{"cmd":"pip install zope.i18n","lang":"bash","label":"Latest stable release"}],"dependencies":[{"reason":"Used for declaring translatable message IDs with domain information.","package":"zope.i18nmessageid","optional":false},{"reason":"Often needed to provide a request object for the translate function, especially in a Zope/Plone context.","package":"zope.globalrequest","optional":true},{"reason":"Underlying library for message catalog handling. Required if compiling .po files.","package":"gettext","optional":true}],"imports":[{"note":"The primary function for manual translation of Message objects or strings.","symbol":"translate","correct":"from zope.i18n import translate"},{"note":"Used to create a factory for message IDs tied to a specific translation domain, often aliased as '_'.","symbol":"MessageFactory","correct":"from zope.i18nmessageid import MessageFactory"},{"note":"Retrieves the current HTTP request object, which is crucial for determining the target language in a web context.","symbol":"getRequest","correct":"from zope.globalrequest import getRequest"}],"quickstart":{"code":"import os\nfrom zope.i18n import translate\nfrom zope.i18nmessageid import MessageFactory\n\n# Simulate a request object for translation context\nclass MockRequest:\n    def __init__(self, lang):\n        self.LANGUAGE_NEGOTIATED = lang\n        self.locale = MockLocale(lang)\n\nclass MockLocale:\n    def __init__(self, lang):\n        self.getLocaleID = lambda: lang\n\n# Define a message factory for your domain\n_ = MessageFactory('my.application')\n\n# A translatable message\nmsg = _('hello_world_id', default='Hello, World!', mapping={'name': 'User'})\n\n# Example of a simple translation service (in a real Zope app, this would be set up)\ndef get_translation_service(request):\n    # In a real Zope setup, this would resolve the utility\n    # For this example, we just return the 'translate' function itself\n    return lambda message, target_language=None, default=None, mapping=None, context=None, domain=None:\n        if target_language == 'de':\n            return f\"Hallo, {mapping.get('name', '')}!\"\n        elif target_language == 'fr':\n            return f\"Bonjour, {mapping.get('name', '')}!\"\n        return default if default else str(message) # Fallback\n\n# Translate the message\n# Often, the request context implicitly provides the target_language\n\nmock_request_en = MockRequest('en')\nmock_request_de = MockRequest('de')\nmock_request_fr = MockRequest('fr')\n\n# Using translate with a mocked context and explicit target language\ntranslated_en = translate(msg, target_language='en', context=mock_request_en, mapping={'name': 'Alice'})\ntranslated_de = translate(msg, target_language='de', context=mock_request_de, mapping={'name': 'Bob'})\ntranslated_fr = translate(msg, target_language='fr', context=mock_request_fr, mapping={'name': 'Charlie'})\n\nprint(f\"English: {translated_en}\")\nprint(f\"German: {translated_de}\")\nprint(f\"French: {translated_fr}\")\n\n# Example for automatic MO file compilation (if 'compile' extra is installed)\nos.environ['ZOPE_I18N_COMPILE_MO_FILES'] = 'true'\n# In a real application, MO files would now be compiled on startup if .po files exist\nprint(f\"\\nZOPE_I18N_COMPILE_MO_FILES env var set: {os.environ.get('ZOPE_I18N_COMPILE_MO_FILES')}\")\n","lang":"python","description":"This quickstart demonstrates how to define a translatable message using `MessageFactory` (commonly aliased as `_`) and then translate it using the `translate` function. It includes a minimal mock for the request context, which is typically provided by the Zope application server for language negotiation. It also hints at the environment variable for automatic MO file compilation."},"warnings":[{"fix":"Ensure your project's `setup.py` and package structure conform to PEP 420 implicit namespaces. This often requires `zc.buildout` version 5 or higher in Zope environments.","message":"Version 6.0 replaced `pkg_resources` namespace declarations with PEP 420 native namespaces. Projects relying on the old namespace package style might break.","severity":"breaking","affected_versions":"6.0+"},{"fix":"Upgrade your Python environment to Python 3.9 or higher. Check the `zope.i18n` PyPI page for specific version compatibility.","message":"Support for Python versions 3.8 and older has been dropped in recent `zope.i18n` versions (e.g., 5.3 dropped 3.8, 5.0 dropped 3.5/3.6).","severity":"breaking","affected_versions":"5.0+"},{"fix":"Ensure the `mapping` passed to `translate` is correctly propagated or consider updating the `Message` object's internal mapping if you intend to merge values. Avoid converting `Message` objects to `unicode` too early if you need to retain domain and default information.","message":"When using `zope.i18n.translate` with a `zope.i18nmessageid.Message` object, explicitly passed `mapping` arguments might be overridden by an empty default mapping from the `Message` object, preventing interpolation.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use a tool like `i18ndude` or set the environment variable `ZOPE_I18N_COMPILE_MO_FILES='true'` in your deployment environment (e.g., `buildout.cfg` for Zope/Plone) to enable automatic compilation of `.po` files to `.mo` files.","message":"Translation (`.mo`) files are often not included in releases or automatically compiled. Manual compilation or specific environment variable setup is required.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"In your `__init__.py` (or similar product setup), declare `YourDomainMessageFactory = MessageFactory('your.domain')` and make it public using `ModuleSecurityInfo('your.packagename').declarePublic('YourDomainMessageFactory')`. Then import it as `from your.packagename import YourDomainMessageFactory as _` in your Restricted Python scripts.","cause":"Attempting to use the `_` (MessageFactory) function in a Zope Restricted Python script without explicitly importing it or declaring it public.","error":"NameError: global name '_' is not defined"},{"fix":"Override the default locale definitions. This typically involves copying the relevant XML locale file (e.g., `de.xml`) from `zope.i18n.locales.data` into your project's locale directory and modifying the `<numbers>` or `<dates>` section as needed.","cause":"Default locale formatters in `zope.i18n.locales` provide specific number/date patterns that might not align with desired display formats, especially for region-specific nuances.","error":"Numbers or dates are formatted incorrectly (e.g., '2.021' instead of '2021' for a year in German)."},{"fix":"Design UI elements with flexibility in mind (e.g., using dynamic sizing, Flexbox, CSS Grid) rather than fixed widths. Provide ample padding and margins. Thorough localization testing is essential to catch these issues early.","cause":"Different languages have varying text lengths (e.g., German words are often longer than English), leading to UI elements not accommodating translated strings.","error":"Translated text overflows UI elements or breaks layout."}]}