Как оптимизировать поддержку мультиязычности в Python?

Здравствуйте. <br/> <br/> У меня есть функция, отвечающая за перевод сообщений, а также файлы с переводами. <br/> <br/> <pre><code class="python">async def _(text, lang):
    file_path = os.path.join(os.path.dirname(__file__), f"{lang}.json")
    if not os.path.exists(file_path):
        return text
    
    async with aiofiles.open(file_path, mode='r') as file:
        lang_data = json.loads(await file.read())
    
    for key in text.split("."):
        lang_data = lang_data.get(key, None)
        if lang_data is None:
            return text
    return lang_data</code></pre> <br/> <br/> Данные о пользователе и его языке хранятся в базе данных. Мне не хотелось бы кэшировать эту информацию, но я также сомневаюсь в правильности написания запроса к базе данных в каждой функции для получения языка пользователя. <br/> <br/> Можете ли вы подсказать, есть ли способ избежать частых обращений к базе данных, или это не имеет смысла и лучше продолжать делать запросы каждый раз?
  • 22 декабря 2024 г. 11:33
Ответы на вопрос 2
Оптимизация поддержки мультиязычности в Python может быть достигнута несколькими способами. Основная проблема, которую вы описали, заключается в частых обращениях к базе данных для получения информации о языке пользователя. Приведу несколько подходов, которые могут помочь оптимизировать ваш код:

### 1. Кэширование данных о языке пользователя
Вместо того чтобы каждый раз делать запрос к базе данных, вы можете временно кэшировать язык пользователя. Это можно реализовать с использованием:
- **Местного переменного кэша** - храните данные в переменных во время работы приложения.
- **Кэширование в памяти** - используйте различные библиотеки для кэширования, например, `cachetools` или `diskcache`.

Пример с использованием словаря для кэширования:

```python
user_language_cache = {}

async def get_user_language(user_id):
    if user_id in user_language_cache:
        return user_language_cache[user_id]

    # Здесь ваш запрос к базе данных для получения языка пользователя
    lang = await fetch_language_from_db(user_id)
    user_language_cache[user_id] = lang
    return lang
```

### 2. Использование Middleware для обработки языков
Если ваше приложение использует веб-фреймворк (например, FastAPI или Flask), можно использовать middleware для установки языка для каждого запроса. Это избавит вас от необходимости запрашивать язык в каждой функции.

Пример на FastAPI:

```python
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def set_language(request: Request, call_next):
    user_id = request.cookies.get("user_id")  # или получить из заголовков/сессии
    lang = await get_user_language(user_id)
    request.state.lang = lang
    response = await call_next(request)
    return response
```

### 3. Оптимизация функции перевода
Ваша функция `_` возвращает текст, если язык пользователя не найден. Убедитесь, что вы используете кэшированные данные, когда это возможно. 

Обновленная функция:

```python
async def translate(text, lang):
    if lang in translations_cache:
        lang_data = translations_cache[lang]
    else:
        file_path = os.path.join(os.path.dirname(__file__), f"{lang}.json")
        if not os.path.exists(file_path):
            translations_cache[lang] = {}
            return text
        
        async with aiofiles.open(file_path, mode='r') as file:
            lang_data = json.loads(await file.read())
            translations_cache[lang] = lang_data

    for key in text.split("."):
        lang_data = lang_data.get(key, None)
        if lang_data is None:
            return text
    return lang_data
```

### 4. Периодическое обновление кэша
Если вы хотите избегать устаревания данных в кэше, можете реализовать стратегию периодического обновления кэша. Например, за 1 минуту или после определенного количества запросов.

### Итог
Кэширование языка пользователя и языковых данных, а также использование middleware для установки языка, когда это возможно, значительно уменьшают количество обращений к базе данных и повышают производительность вашего приложения. Выберете подход, который больше подходит для ваших нужд и архитектуры приложения.
А этот файл вообще изменяется? Если нет, то читай на старте и используй уже готовое
Похожие вопросы