npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uzum-tech/i18n

v1.1.1

Published

Uzum i18n

Downloads

231

Readme

О библиотеке

Uzum I18n — это облачная система интернационализации, которая позволяет управлять переводами через централизованную админку и автоматически синхронизировать их с вашими приложениями.

🎯 Основные концепции

  • Централизованное управление: Все переводы хранятся в облаке и управляются через веб-интерфейс (Бэкенд реализован только для Uzum. Вам нужно реализовать его самостоятельно)
  • Фреймворк-агностичность: Работает с любым JavaScript фреймворком через единый адаптер
  • Реактивность: Автоматически обновляет интерфейс при смене языка или загрузке переводов
  • Изоляция окружений: Отдельные переводы для development, staging и production

✨ Уникальные особенности

  1. Адаптивная интеграция — библиотека подстраивается под систему реактивности вашего фреймворка
  2. Облачная синхронизация — переводы загружаются из облака, не нужно хранить их в коде
  3. Горячая замена переводов — изменения в админке мгновенно отражаются в приложении
  4. Изоляция по окружениям — разные переводы для разных стендов через VPN
  5. Универсальный API — один код работает везде, меняется только адаптер реактивности
  6. Автоопределение языка по URL — если URL начинается с пути вида /ru, язык при инициализации выбирается автоматически. Приоритетность: URL путь → localStoragedefaultLanguageCode → язык по умолчанию в проекте → язык браузера
  7. Сохранение выбора пользователя — если язык не указан в URL, а пользователь ранее уже открывал страницу и выбирал язык, будет восстановлен именно его последний выбор из localStorage, а не язык по умолчанию

Package version License

Содержание

Установка

Пакетный менеджер

Используя npm:

npm i @uzum-tech/i18n

Используя yarn:

yarn add @uzum-tech/i18n

Использование

Vue

Примеры указаны для того, чтобы вы могли наглядно увидеть как можно использовать пакет и быстро разобраться в основных принципах работы. Любые решения могут зависеть от предпочтений принятых в вашем проекте.

  1. Заводим переменную окружения. Чтобы во всех стендах были одинаковые переводы, можно везде использовать 'production'.
# .env

VITE_I18N_ENV=production
  1. Заводим переменную в файле конфига и прокидываем туда значение переменной окружения.
// @/shared/config/global-config.ts

export const globalConfig = {
  i18n: {
    env: import.meta.env.VITE_I18N_ENV
  }
} as const;
  1. Дополняем/Создаем файл локализации i18n.ts. Создаем экземпляр локализации Localization и 1ым аргументом передаем экземпляр i18n, который реализует интерфейс I18n. Инстанс созданный методом createI18n из пакета vue-i18n по умолчанию реализует его. 2ым аргументом передаем опции LocalizationOptions.
// @/shared/plugins/i18n.ts

// Если есть автоимпорты, то можно не импортировать ref
import { ref } from 'vue';
import { createI18n } from 'vue-i18n';
import { Localization } from '@uzum-tech/i18n';
import { globalConfig } from '../config/global-config';

const i18n = createI18n({
  locale: 'ru',
  legacy: false,
  pluralRules: {
    ru: YOUR_PLURAL_FUNCTION,
    uz: YOUR_PLURAL_FUNCTION
  }
});

export const localization = new Localization(i18n, {
  projectKey: 'YOUR_PROJECT_KEY',
  env: globalConfig.i18n.env,
  ref
});

export default i18n;
  1. Реализуем обертки для лоадинга и смены языка.
// @/app/components/app-layout-header/useAppLayoutHeader.ts

import { localization } from '@/shared/plugins/i18n';

export default function useAppLayoutHeader() {
  const languagesLoading = computed<boolean>(
    () => localization.languagesLoading.value || localization.messagesLoading.value
  );

  const selectLang = (value: string) => {
    localization.changeLanguage(value);
  };

  return {
    languagesLoading,
    selectLang
  };
}
  1. Используем обертки для лоадинга и смены языка в шаблоне.
// @/app/components/app-layout-header/AppLayoutHeader.vue

<script lang="ts" scoped>
import useAppLayoutHeader from './useAppLayoutHeader';

const {
  languagesLoading,
  selectLang
} = useAppLayoutHeader();
</script>

<template>
  ...
    <u-dropdown
      ...
      @select="selectLang"
    >
      <u-button
        ...
        :loading="languagesLoading"
      >
        ...
      </u-button>
    </u-dropdown>
  ...
</template>

React

  1. Создаем файл переменных окружения:
# .env

REACT_APP_I18N_ENV=production
  1. Создаем файл конфигурации:
// src/shared/config/global-config.ts

export const globalConfig = {
  i18n: {
    env: process.env.REACT_APP_I18N_ENV
  }
} as const;
  1. Создаем файл локализации с React-совместимым i18n объектом:
// src/shared/plugins/i18n.ts

import { useState } from 'react';
import { Localization } from '@uzum-tech/i18n';
import { globalConfig } from '../config/global-config';

// Создаем React-совместимый i18n объект
const createReactI18n = () => {
  const messages: Record<string, Record<string, string>> = {};
  let currentLocale = 'ru';
  let missingHandler: ((locale: string, key: string) => void) | null = null;

  return {
    global: {
      locale: currentLocale,
      setLocaleMessage: (language: string, msgs: Record<string, string>) => {
        messages[language] = msgs;
      },
      mergeLocaleMessage: (language: string, msgs: Record<string, string>) => {
        messages[language] = { ...messages[language], ...msgs };
      },
      setMissingHandler: (handler: (locale: string, key: string) => void) => {
        missingHandler = handler;
      }
    }
  };
};

// Создаем ref функцию для React
const createRef = <T>(value: T) => {
  const [state, setState] = useState(value);
  return {
    get value() {
      return state;
    },
    set value(newValue: T) {
      setState(newValue);
    }
  };
};

const i18n = createReactI18n();

export const localization = new Localization(i18n, {
  projectKey: 'YOUR_PROJECT_KEY',
  env: globalConfig.i18n.env,
  ref: createRef
});

export default i18n;
  1. Создаем хук для работы с локализацией:
// src/app/components/app-layout-header/useAppLayoutHeader.ts

import { useMemo } from 'react';
import { localization } from '@/shared/plugins/i18n';

export default function useAppLayoutHeader() {
  const languagesLoading = useMemo(() =>
    localization.languagesLoading.value || localization.messagesLoading.value,
    [localization.languagesLoading.value, localization.messagesLoading.value]
  );

  const selectLang = (value: string) => {
    localization.changeLanguage(value);
  };

  return {
    languagesLoading,
    selectLang
  };
}
  1. Используем хук в React компоненте:
// src/app/components/app-layout-header/AppLayoutHeader.tsx

import React from 'react';
import useAppLayoutHeader from './useAppLayoutHeader';

const AppLayoutHeader: React.FC = () => {
  const { languagesLoading, selectLang } = useAppLayoutHeader();

  return (
    <div>
      {/* Ваш UI */}
      <select onChange={(e) => selectLang(e.target.value)}>
        <option value="ru">Русский</option>
        <option value="uz">O'zbek</option>
        <option value="en">English</option>
      </select>
      {languagesLoading && <div>Загрузка...</div>}
    </div>
  );
};

export default AppLayoutHeader;

Angular

  1. Создаем файл переменных окружения:
// src/environments/environment.ts

export const environment = {
  production: false,
  i18nEnv: 'production'
};
  1. Создаем сервис для глобальной конфигурации:
// src/app/shared/config/global-config.service.ts

import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root'
})
export class GlobalConfigService {
  public readonly i18n = {
    env: environment.i18nEnv
  };
}
  1. Создаем сервис локализации:
// src/app/shared/services/i18n.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Localization } from '@uzum-tech/i18n';
import { GlobalConfigService } from '../config/global-config.service';

@Injectable({
  providedIn: 'root'
})
export class I18nService {
  private messages: Record<string, Record<string, string>> = {};
  private currentLocale$ = new BehaviorSubject('ru');
  private missingHandler: ((locale: string, key: string) => void) | null = null;

  private i18n = {
    global: {
      get locale() {
        return this.currentLocale$.value;
      },
      setLocaleMessage: (language: string, msgs: Record<string, string>) => {
        this.messages[language] = msgs;
      },
      mergeLocaleMessage: (language: string, msgs: Record<string, string>) => {
        this.messages[language] = { ...this.messages[language], ...msgs };
      },
      setMissingHandler: (handler: (locale: string, key: string) => void) => {
        this.missingHandler = handler;
      }
    }
  };

  public readonly localization: Localization;

  constructor(private globalConfig: GlobalConfigService) {
    // Создаем Angular-совместимую ref функцию
    const createRef = <T>(value: T) => {
      const subject = new BehaviorSubject(value);
      return {
        get value() {
          return subject.value;
        },
        set value(newValue: T) {
          subject.next(newValue);
        }
      };
    };

    this.localization = new Localization(this.i18n, {
      projectKey: 'YOUR_PROJECT_KEY',
      env: this.globalConfig.i18n.env,
      ref: createRef
    });
  }

  get languagesLoading() {
    return this.localization.languagesLoading.value || this.localization.messagesLoading.value;
  }

  selectLang(value: string) {
    this.localization.changeLanguage(value);
  }
}
  1. Создаем компонент для работы с локализацией:
// src/app/components/app-layout-header/app-layout-header.component.ts

import { Component } from '@angular/core';
import { I18nService } from '@/shared/services/i18n.service';

@Component({
  selector: 'app-layout-header',
  template: `
    <div>
      <!-- Ваш UI -->
      <select (change)="selectLang($event)">
        <option value="ru">Русский</option>
        <option value="uz">O'zbek</option>
        <option value="en">English</option>
      </select>
      <div *ngIf="languagesLoading">Загрузка...</div>
    </div>
  `
})
export class AppLayoutHeaderComponent {
  constructor(private i18nService: I18nService) {}

  get languagesLoading() {
    return this.i18nService.languagesLoading;
  }

  selectLang(event: Event) {
    const target = event.target as HTMLSelectElement;
    this.i18nService.selectLang(target.value);
  }
}

Preact

  1. Создаем файл переменных окружения:
# .env

PREACT_APP_I18N_ENV=production
  1. Создаем файл конфигурации:
// src/shared/config/global-config.ts

export const globalConfig = {
  i18n: {
    env: process.env.PREACT_APP_I18N_ENV
  }
} as const;
  1. Создаем файл локализации:
// src/shared/plugins/i18n.ts

import { signal } from '@preact/signals';
import { Localization } from '@uzum-tech/i18n';
import { globalConfig } from '../config/global-config';

// Создаем Preact-совместимый i18n объект
const createPreactI18n = () => {
  const messages: Record<string, Record<string, string>> = {};
  const currentLocale = signal('ru');
  let missingHandler: ((locale: string, key: string) => void) | null = null;

  return {
    global: {
      get locale() {
        return currentLocale.value;
      },
      setLocaleMessage: (language: string, msgs: Record<string, string>) => {
        messages[language] = msgs;
      },
      mergeLocaleMessage: (language: string, msgs: Record<string, string>) => {
        messages[language] = { ...messages[language], ...msgs };
      },
      setMissingHandler: (handler: (locale: string, key: string) => void) => {
        missingHandler = handler;
      }
    }
  };
};

// Создаем ref функцию для Preact
const createRef = <T>(value: T) => {
  const sig = signal(value);
  return {
    get value() {
      return sig.value;
    },
    set value(newValue: T) {
      sig.value = newValue;
    }
  };
};

const i18n = createPreactI18n();

export const localization = new Localization(i18n, {
  projectKey: 'YOUR_PROJECT_KEY',
  env: globalConfig.i18n.env,
  ref: createRef
});

export default i18n;
  1. Создаем хук для работы с локализацией:
// src/app/components/app-layout-header/useAppLayoutHeader.ts

import { computed } from '@preact/signals';
import { localization } from '@/shared/plugins/i18n';

export default function useAppLayoutHeader() {
  const languagesLoading = computed(() =>
    localization.languagesLoading.value || localization.messagesLoading.value
  );

  const selectLang = (value: string) => {
    localization.changeLanguage(value);
  };

  return {
    languagesLoading,
    selectLang
  };
}
  1. Используем хук в Preact компоненте:
// src/app/components/app-layout-header/AppLayoutHeader.tsx

import { h } from 'preact';
import useAppLayoutHeader from './useAppLayoutHeader';

const AppLayoutHeader = () => {
  const { languagesLoading, selectLang } = useAppLayoutHeader();

  return (
    <div>
      {/* Ваш UI */}
      <select onChange={(e) => selectLang((e.target as HTMLSelectElement).value)}>
        <option value="ru">Русский</option>
        <option value="uz">O'zbek</option>
        <option value="en">English</option>
      </select>
      {languagesLoading.value && <div>Загрузка...</div>}
    </div>
  );
};

export default AppLayoutHeader;

Svelte

  1. Создаем файл переменных окружения:
# .env

VITE_I18N_ENV=production
  1. Создаем файл конфигурации:
// src/shared/config/global-config.ts

export const globalConfig = {
  i18n: {
    env: import.meta.env.VITE_I18N_ENV
  }
} as const;
  1. Создаем файл локализации:
// src/shared/plugins/i18n.ts

import { writable } from 'svelte/store';
import { Localization } from '@uzum-tech/i18n';
import { globalConfig } from '../config/global-config';

// Создаем Svelte-совместимый i18n объект
const createSvelteI18n = () => {
  const messages: Record<string, Record<string, string>> = {};
  const currentLocale = writable('ru');
  let missingHandler: ((locale: string, key: string) => void) | null = null;

  return {
    global: {
      locale: currentLocale,
      setLocaleMessage: (language: string, msgs: Record<string, string>) => {
        messages[language] = msgs;
      },
      mergeLocaleMessage: (language: string, msgs: Record<string, string>) => {
        messages[language] = { ...messages[language], ...msgs };
      },
      setMissingHandler: (handler: (locale: string, key: string) => void) => {
        missingHandler = handler;
      }
    }
  };
};

// Создаем ref функцию для Svelte
const createRef = <T>(value: T) => {
  const store = writable(value);
  return {
    get value() {
      let currentValue: T;
      const unsubscribe = store.subscribe(val => currentValue = val);
      unsubscribe();
      return currentValue!;
    },
    set value(newValue: T) {
      store.set(newValue);
    }
  };
};

const i18n = createSvelteI18n();

export const localization = new Localization(i18n, {
  projectKey: 'YOUR_PROJECT_KEY',
  env: globalConfig.i18n.env,
  ref: createRef
});

export default i18n;
  1. Создаем store для работы с локализацией:
// src/app/stores/i18n.ts

import { derived } from 'svelte/store';
import { localization } from '@/shared/plugins/i18n';

export const languagesLoading = derived(
  [localization.languagesLoading, localization.messagesLoading],
  ([langLoading, msgLoading]) => langLoading || msgLoading
);

export const selectLang = (value: string) => {
  localization.changeLanguage(value);
};
  1. Используем store в Svelte компоненте:
<!-- src/app/components/AppLayoutHeader.svelte -->

<script lang="ts">
  import { languagesLoading, selectLang } from '@/app/stores/i18n';

  const handleLanguageChange = (event: Event) => {
    const target = event.target as HTMLSelectElement;
    selectLang(target.value);
  };
</script>

<div>
  <!-- Ваш UI -->
  <select on:change={handleLanguageChange}>
    <option value="ru">Русский</option>
    <option value="uz">O'zbek</option>
    <option value="en">English</option>
  </select>

  {#if $languagesLoading}
    <div>Загрузка...</div>
  {/if}
</div>

Описание типов

Интерфейс LocalizationOptions

| Название | Тип | Значение по умолчанию | Описание | | -- | -- | -- | -- | | projectKey | string | Отсутствует. Необходимо передать. | Ключ проекта, определяется при создании проекта через админку. Для консистентности придерживаемся kebab-case регистра, латиницы и чисел по необходимости. | | env | 'local' \| 'development' \| 'staging' \| 'production' | 'production' | Все стенды кроме 'production' доступны только через VPN. Каждый стенд изолирован, как и данные в них. | | defaultLanguageCode | string | undefined | Язык по умолчанию. Используется как запасной вариант, если язык не удалось определить из URL пути или localStorage. Приоритетность выбора языка при инициализации: URL путь → localStoragedefaultLanguageCode → язык по умолчанию в проекте → язык браузера. | | ref | <T>(value: T) => { value: T (get/set) } | undefined | Функция, создающая реактивное состояние с геттером и сеттером. Нужно чтобы вы могли реактивно следить за состояниями: languagesLoading, messagesLoading |

Интерфейс I18n

| Название | Тип | Значение по умолчанию | Описание | | -- | -- | -- | -- | | global | I18nGlobal | Отсутствует. Необходимо передать. | Объект содержащий свойства и методы для работы с переводами и языками. |

Интерфейс I18nGlobal

| Название | Тип | Значение по умолчанию | Описание | | -- | -- | -- | -- | | locale | string \| { value: string } | Отсутствует. Необходимо передать. | Выбранный язык. | | setLocaleMessage | (language: string, messages: Record<string, string>) => void | Отсутствует. Необходимо передать. | Метод устанавливающий все ключи языка. | | mergeLocaleMessage | (language: string, messages: Record<string, string>) => void | Отсутствует. Необходимо передать. | Метод добавляющий новые ключи в язык. | | setMissingHandler | (handler: I18nMissingHandler) => void | Отсутствует. Необходимо передать. | Метод устанавливающий коллбэк обрабатывающий пустые значения. |

Лицензия

MIT license