Custom Loaders
You can extend doti18n to support custom file formats by implementing a custom loader. Loaders are automatically registered upon class definition.
Requirements#
To create a loader, define a class that inherits from doti18n.loaders.BaseLoader and meets these criteria:
file_extension: A string attribute defining the extension (e.g.,.custom).__init__: Must accept astrict: boolargument.loadmethod: Must read the file and return data in one of these formats:- Single locale:
{ "en": { ... } }(derived from filename). - Multilocale:
[ {...}, {...} ]. (with key__locale__inside each dict).
- Single locale:
Execution order
You must define or import your custom loader before creating the LocaleData instance.
Why? The Main Loader(doti18n.loaders.Loader) register all available loaders at initialization. If your custom loader is defined later, it won't be registered and won't be used.
Example Implementation#
import os
from typing import Union, Optional, Dict, List
from pathlib import Path
from doti18n.loaders import BaseLoader
# import custom_parser
class CustomLoader(BaseLoader):
file_extension = ".custom"
def __init__(self, strict: bool = False):
self._strict = strict
def load(self, filepath: Union[str, Path]) -> Optional[Union[Dict, List[dict]]]:
# 1. Read file content
with open(filepath, encoding='utf-8') as file:
content = file.read()
# 2. Parse data (using your custom logic)
# data = custom_parser.parse(content)
data = {"mock_key": "mock_value"}
# 3. Determine locale (usually from filename)
locale = os.path.splitext(os.path.basename(filepath))[0]
# 4. Return strictly typed dict: {locale: data}
return {locale: data}
Tip
ICUMF and macros processing in the main loader (doti18n.loaders.Loader). That means your custom loader only needs to focus on parsing the file and returning the raw data.