# Get Translations
Source: https://docs.unlingo.com/api-reference/translations/get-translations
GET https://api.unlingo.com/v1/translations
Retrieve translations for your application
## Overview
This is the primary endpoint for fetching translations from Unlingo. It returns ready-to-use translation data that can be directly integrated with any i18n library.
## Authentication
You can authenticate using either method:
Your API key passed in the header `x-api-key: YOUR_API_KEY`
Bearer token with your API key `Authorization: Bearer YOUR_API_KEY`
## Required Parameters
The release tag to fetch translations from **Examples**: `1.0.0`, `staging`, `production`
The namespace containing your translations **Examples**: `translation`, `auth`, `dashboard`
The language code for the translations **Examples**: `en`, `es`, `fr`, `de`, `zh`
## Example Request
```bash cURL
curl -X GET "https://api.unlingo.com/v1/translations?release=1.0.0&namespace=translation&lang=en" \
-H "x-api-key: YOUR_API_KEY"
```
```bash cURL (Bearer)
curl -X GET "https://api.unlingo.com/v1/translations?release=1.0.0&namespace=translation&lang=en" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```javascript JavaScript
const response = await fetch('https://api.unlingo.com/v1/translations?release=1.0.0&namespace=translation&lang=en', {
headers: {
'x-api-key': 'YOUR_API_KEY',
},
});
const translations = await response.json();
```
## Response
The endpoint returns translation data as a JSON object ready for use with i18n libraries. No nested objects - just your translations exactly as they should be used.
```json Response
{
"welcome": "Welcome to our application",
"login": "Sign In",
"logout": "Sign Out",
"nav": {
"home": "Home",
"about": "About",
"contact": "Contact"
},
"buttons": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete"
},
"messages": {
"success": "Operation completed successfully",
"error": "An error occurred"
}
}
```
# Namespaces
Source: https://docs.unlingo.com/concepts/namespaces
Organize your translations with namespaces for better structure and maintainability
## What are Namespaces?
**Namespaces** are logical containers within a project that group related translations together. They help organize your translation keys by feature, component, or any other logical division that makes sense for your application.
Think of namespaces as folders in a file system - they provide structure and help prevent naming conflicts while making translations easier to manage.
## Why Use Namespaces?
Group related translations together for better maintainability
Isolate different features or components to avoid conflicts
Allow different teams to work on different namespaces independently
Load only the translations you need, reducing bundle size
## Namespace Structure
A typical application might use this namespace structure:
```
Project: E-commerce Website
├── common/ # Shared UI elements
│ ├── buttons
│ ├── navigation
│ └── forms
├── product-catalog/ # Product listing and details
│ ├── filters
│ ├── search
│ └── product-card
├── checkout/ # Purchase flow
│ ├── cart
│ ├── payment
│ └── confirmation
└── user-account/ # User profile and settings
├── profile
├── orders
└── preferences
```
## Creating Namespaces
### Via Dashboard
Go to your project dashboard and select the project you want to work withClick on the "Namespaces" tab in your project navigationClick "Create Namespace" and fill in the details.By default new namespaces are created with `main` version.
## Namespace Versioning
Each namespace can have different versions, allowing for independent updates.
## Best Practices
### Keep Namespaces Focused
Avoid creating overly broad namespaces that contain unrelated translations. This makes maintenance difficult and
reduces the benefits of organization.
#### Good: Focused Namespaces
```
auth/ # Only authentication-related
product-search/ # Only search functionality
user-preferences/ # Only user settings
```
#### Avoid: Overly Broad Namespaces
```
misc/ # Too vague
frontend/ # Too broad
translations/ # Doesn't provide organization
```
## Troubleshooting
**Verify that:** - The namespace name is spelled correctly - The namespace exists in your project - Your API key
has access to the namespace - The namespace is included in the current release
## Next Steps
Understand how to version your namespace translations
Package namespaces into deployable releases
# Projects
Source: https://docs.unlingo.com/concepts/projects
Understanding Unlingo projects and how to organize your translations
## What are Projects?
A **Project** in Unlingo represents a single application or product that requires internationalization. Projects serve as the top-level container for organizing all translation-related resources including namespaces, versions, releases, and API keys.
## Project Structure
Each project contains:
* **Namespaces**: Logical groupings of related translations
* **Releases**: Versioned collections of translations ready for deployment
* **Screenshots**: Visual translation mapping for UI elements
* **API Keys**: Authentication credentials scoped to the project
* **Settings**: Configuration options
## Creating Projects
### Via Dashboard
Sign in to your Unlingo account and go to the main dashboardClick the "Create Project" button on your dashboardEnter the required information
## Best Practices
### Project Organization
**One Project per Application**: Create separate projects for different applications, even if they share some
translations. This provides better isolation and access control.
#### Good Project Structure
```
- My E-commerce Website (Project)
├── common (Namespace)
├── product-catalog (Namespace)
├── checkout (Namespace)
└── user-account (Namespace)
- My Mobile App (Project)
├── onboarding (Namespace)
├── main-navigation (Namespace)
└── settings (Namespace)
```
#### Avoid This Structure
```
- All Company Products (Project)
├── website-common (Namespace)
├── website-product-catalog (Namespace)
├── mobile-onboarding (Namespace)
└── mobile-navigation (Namespace)
```
## Troubleshooting
Check that you haven't reached your plan's project limit. Free accounts are limited to 1 project.
Ensure that your API key is associated with the correct project
## Next Steps
Organize your translations within projects using namespaces
Package your translations for deployment
# Releases
Source: https://docs.unlingo.com/concepts/releases
Learn how to create and manage releases to publish your translations for production use
## Overview
Releases in Unlingo are snapshots of your translations that are published and made available for production use. They represent stable, tested versions of your content that applications can reliably consume through the API.
Think of releases as Git tags - they create a reference to a specific version of your translations, that you can change on the fly without changing application code.
## Creating Releases
Create a release and assign an existing versions:
1. Navigate to your project's **Releases** tab
2. Click **Create Release**
3. Select the **namespace**
4. Select the **version** from namespace
5. Repeat steps 3-4 if you have multiple namespaces
6. Enter **release name** (e.g., `1.2.0`)
7. Add **release description** (optional)
8. Click **Create Release**
### Release Numbering
Releases support various numbering schemes:
**Semantic Versioning (Recommended):**
```
1.0.0 # Initial release
1.0.1 # Patch release
1.1.0 # Minor release
2.0.0 # Major release
```
**Date-based Versioning:**
```
2024.01.15 # Release date
2024-Q1 # Quarterly release
2024-W03 # Weekly release
```
**Named Releases:**
```
winter-2024 # Seasonal release
mobile-launch # Feature release
hotfix-jan # Emergency release
```
## Release Management
### Editing Releases
You can modify certain aspects of published releases:
1. **Description**: Update description (it won't affect any usage)
2. **Namespaces and Versions**: You can modify selected namespaces and versions
### Deleting Releases
To delete a release:
1. Go to the **Releases** tab
2. Find the release to delete
3. Click the **⋮** menu
4. Select **Delete Release**
5. Confirm the deletion
Deleting a release immediately breaks any applications using that release number in their API calls. Ensure no
active integrations depend on the release before deletion.
## API Integration
### Fetching Release Content
Applications consume releases through the API:
```javascript
// Fetch specific release
const translations = await fetch('/v1/translations', {
params: {
namespace: 'common',
release: '1.2.0', // Release name
lang: 'en',
},
});
```
## Monitoring and Analytics
### Release Usage
Track how releases are being used:
* **API calls per release**: Which releases are active
* **Language distribution**: Most requested languages
* **Namespace popularity**: Most accessed namespaces
## Troubleshooting
* **Problem**:
* Release missing some expected translations.
* **Solutions**:
* Verify release name in API call
* Verify source version had complete translations
* Check if languages were properly included
* Ensure version wasn't modified during release creation
* Set updated version
## Next Steps
Understand the relationship between versions and releases
Learn how to consume releases in your application
# Screenshots
Source: https://docs.unlingo.com/concepts/screenshots
Learn how to use visual screenshots to map translations directly onto your UI elements
## Overview
Screenshots in Unlingo provide a visual approach to translation management by allowing you to upload images of your application's interface and map translation keys directly to UI elements. This creates an intuitive bridge between your visual design and your translation content.
This feature is particularly powerful for design teams, non-technical users, and complex interfaces where the relationship between translation keys and UI elements needs to be clearly visualized.
## Key Concepts
### Visual Translation Mapping
Screenshots enable you to:
* **Upload UI images**: Capture screens from your application
* **Place containers**: Mark translatable areas on the interface
* **Assign keys**: Connect translation keys to visual elements
* **Edit content**: Update translations directly in visual context
* **Collaborate**: Share visual context with team members
### Screenshot Structure
Each screenshot contains:
* **Image file**: The actual screenshot (PNG, JPG, JPEG)
* **Containers**: Colored boxes marking translatable areas
* **Key mappings**: Links between containers and translation keys
* **Metadata**: Name, description, upload date, dimensions
## Working Modes
Screenshots support two distinct working modes:
### Edit Mode
**Purpose**: Container placement and configuration
**Use case**: Setting up the visual mapping structure
**Features**:
* Place containers on UI elements
* Resize and position containers precisely
* Customize container colors for organization
* Add descriptions for context
* Delete or modify containers
**Workflow**:
1. Switch to Edit Mode
2. Click "Add Container"
3. Click on the screenshot to place containers
4. Drag edges to resize containers
5. Add descriptions for clarity
### Translate Mode
**Purpose**: Translation key assignment and content editing
**Use case**: Actual translation work
**Features**:
* Select namespace, version, and language
* Assign translation keys to containers
* Edit translation values inline
* Save changes back to language files
**Workflow**:
1. Select translation context (namespace/version/language)
2. Click containers to select them
3. Assign translation keys from the language file
4. Edit values directly in the interface
5. Save changes to update translations
## Screenshot Management
### Uploading Screenshots
1. Navigate to the **Screenshots** tab in your project
2. Click **Add Screenshot**
3. Select an image file (PNG, JPG, JPEG up to 10MB)
4. Enter a descriptive name
5. Add an optional description
6. Click **Upload**
### Screenshot Grid
The screenshot overview displays:
* **Thumbnail preview**: Visual preview of each screenshot
* **Name and description**: Identifying information
* **Metadata**: Dimensions, file size, upload date
* **Quick actions**: Edit, Translate, Delete buttons
## Container System
### Creating Containers
#### In Edit Mode:
1. Select container color from color picker
2. Click **Add Container**
3. Click on the screenshot where you want to place the container
4. Container appears with default size
5. Drag handles to resize as needed
#### Container Properties:
* **Position**: X, Y coordinates (percentage-based)
* **Size**: Width and height (percentage-based)
* **Color**: Background color for visual organization
* **Description**: Optional context for team members
### Container Interaction
#### Resizing Containers
* Drag corner handles to resize proportionally
* Drag edge handles to resize width or height only
* Minimum size constraints prevent overly small containers
* Maximum size constraints prevent containers exceeding image bounds
* Click and drag container body to reposition
#### Container Colors
Organize containers by color-coding:
```css
/* Common color schemes */
Blue (#3b82f6) - Headers and titles
Green (#10b981) - Success messages and buttons
Red (#ef4444) - Error messages and warnings
Purple (#8b5cf6) - Navigation and links
Yellow (#f59e0b) - Input fields and forms
Gray (#6b7280) - Secondary content
```
### Container Descriptions
Add context to help translators understand the purpose:
```
Examples:
"Main page heading - should be concise and impactful"
"Error message for invalid email format"
"Call-to-action button - keep under 20 characters"
"Navigation menu item for user profile section"
```
## Translation Workflow
### Setting Up Translation Context
Before assigning keys, establish the translation context:
1. **Select Namespace**: Choose the namespace containing your translations
2. **Select Version**: Pick the version you're working with
3. **Select Language**: Choose the target language for translation
4. **Lock Context**: System locks selections to prevent accidents
The workflow selector provides a step-by-step process ensuring you select all required elements before enabling translation features.
### Assigning Translation Keys
#### Key Assignment Process:
1. Click on a container to select it
2. Click **Assign Key** button
3. Search available translation keys
4. Select the appropriate key from the list
5. Key is automatically mapped to the container
#### Key Search and Selection:
* **Search functionality**: Find keys by name or content
* **Type indicators**: Visual badges show data types
* **Key preview**: See current values before assignment
### Value Editing
#### Inline Editing:
1. Click on a mapped container
2. View assigned keys in the sidebar
3. Click on a key's value to edit
4. Make changes inline
5. Changes are tracked as "pending"
6. Save all changes when ready
#### Change Management:
* **Pending changes**: Yellow highlighting indicates unsaved edits
* **Change counter**: Shows number of modified values
## Advanced Features
### Multi-Language Support
Work with multiple languages in the same screenshot:
1. Set up containers in Edit Mode
2. Switch to Translate Mode for first language
3. Assign keys and edit values
4. Change language selection
5. Same containers, different language values
## Performance Optimization
### Image Optimization
Optimize screenshots for better performance:
* **File size**: Compress images without losing clarity
* **Dimensions**: Use appropriate resolution for display
* **Format**: Choose optimal format (PNG for UI, JPEG for photos)
### Container Efficiency
Optimize container management:
* **Minimize containers**: Don't over-map every element
* **Strategic placement**: Focus on translatable content only
## Troubleshooting
* **Problem**:
* Image upload fails or hangs.
* **Solutions**:
* Check file size (must be under 10MB)
* Verify image format (PNG, JPG, JPEG only)
* Test with smaller image first
* Check internet connection stability
* Try different browser if issues persist
* **Problem**:
* Containers appear in wrong locations.
* **Solutions**:
* Ensure click coordinates are within image bounds
* Try using a different zoom level
* Refresh page and try again
* **Problem**:
* Expected keys don't appear in key selection.
* **Solutions**:
* Verify correct language is selected
* Check if keys exist in the selected version
* Ensure translation context is properly locked
* Try refreshing the language data
* Verify key naming and structure
## Next Steps
Integrate with i18next
Integrate with next-intl
# Translations
Source: https://docs.unlingo.com/concepts/translations
Learn how to create, edit, and manage translations using Unlingo's powerful editor interface
## Overview
Translations in Unlingo are the actual content that gets displayed to users in different languages. The translation system supports complex nested structures, various data types, and provides a powerful visual editor for managing your multilingual content.
Unlingo's editor provides both tree view and JSON editing modes, making it accessible for both non-technical translators and developers who prefer working with code.
## Translation Structure
### Nested Keys
Translations are organized in a hierarchical structure using dot notation:
```json
{
"common": {
"buttons": {
"save": "Save",
"cancel": "Cancel",
"submit": "Submit"
},
"navigation": {
"home": "Home",
"about": "About Us",
"contact": "Contact"
}
},
"auth": {
"login": {
"title": "Welcome Back",
"subtitle": "Please sign in to continue",
"form": {
"email": "Email Address",
"password": "Password",
"remember": "Remember me"
}
}
}
}
```
**Accessing in code:**
```javascript
t('common.buttons.save'); // "Save"
t('auth.login.title'); // "Welcome Back"
t('auth.login.form.email'); // "Email Address"
```
### Data Types
Unlingo supports all JSON data types for translation values:
#### Strings
```json
{
"welcome": "Welcome to our application",
"description": "This is a longer description text",
"greeting": "Hello, {{name}}!"
}
```
#### Numbers
```json
{
"maxItems": 100,
"price": 29.99,
"version": 2.1
}
```
#### Booleans
```json
{
"isEnabled": true,
"showAdvanced": false,
"debugMode": false
}
```
#### Arrays
```json
{
"header": [
{
"title": "Dashboard",
"subtitle": "Manage your account"
},
{
"title": "Analytics",
"subtitle": "Track your activity"
}
]
}
```
#### Objects
```json
{
"header": {
"title": "Dashboard",
"subtitle": "Manage your account"
}
}
```
## Editor Interface
### Tree View Mode
The default tree view provides a hierarchical interface:
* **Expandable nodes**: Click to expand/collapse sections
* **Key organization**: See the structure of your translations
* **Value editing**: Click values to edit directly
* **Type indicators**: Visual indicators for different data types
* **Search functionality**: Find keys quickly across the tree
#### Adding Keys
1. Click the **"+"** button in selected node or **"Add Key"** button at the top
2. Choose parent key if needed (optional, by default new keys are added to root level)
3. Enter key name and initial value
4. Select data type (string, number, boolean)
#### Deleting Keys
1. Select the key to delete
2. Click the trash icon
3. Confirm deletion in the dialog
4. Key and all children are removed
Deleting a key removes it and all nested children. This action cannot be undone. Also all languages in selected
version will be affected after Save.
### JSON Edit Mode
Switch to JSON mode for direct code editing:
* **Error detection**: Real-time validation
* **Auto-formatting**: Automatic code formatting
* **Bulk editing**: Make large changes quickly
#### JSON Mode Features
* **Schema validation**: Ensures valid JSON structure
* **Type checking**: Validates data types
### Add Key Modal
The Add Key modal provides a guided interface for creating new translations:
#### Key Information
* **Key Name**: The identifier for the translation
* **Key Path**: Full dot notation path
* **Parent Key**: Context within the hierarchy
#### Value Configuration
* **Data Type**: String, Number, Boolean, Object, Array
* **Initial Value**: Starting content
## Working with Translations
### Creating Content
#### Simple Text
```json
{
"welcome": "Welcome to our application"
}
```
#### With Variables
```json
{
"greeting": "Hello, {{username}}! Welcome back.",
"itemCount": "You have {{count}} {{count, plural, one {item} other {items}}}"
}
```
#### Nested Structure
```json
{
"dashboard": {
"header": {
"title": "Dashboard",
"subtitle": "Manage your account"
},
"sections": {
"overview": "Overview",
"analytics": "Analytics",
"settings": "Settings"
}
}
}
```
### Editing Workflows
#### In-Place Editing
1. Navigate to the key in tree view
2. Click the value to start editing
3. Make changes in the inline editor
4. Press Apply button
#### Batch Editing
1. Switch to JSON edit mode
2. Make multiple changes to the JSON structure
3. Validate changes with the syntax checker
4. Save all changes at once
#### Find and Replace
1. Use the search bar to find specific text
2. Use browser find (Ctrl+F) in JSON mode
3. Replace values across multiple keys
4. Filter results by key path or value content
### Validation and Quality Control
#### Automatic Validation
* **JSON syntax**: Ensures valid structure
* **Key naming**: Validates naming conventions
* **Data types**: Checks type consistency
* **Required fields**: Identifies missing values
#### Translation Completeness
* **Empty values**: Indicated with warnings
## Troubleshooting
* **Problem**:
* Edits are not being persisted.
* **Solutions**:
* Check network connectivity
* Look for validation errors
* **Problem**:
* Invalid JSON preventing saves.
* **Solutions**:
* Check for missing commas or brackets
* Use tree view mode for complex edits
* **Problem**:
* Keys not appearing in application.
* **Solutions**:
* Verify key path matches code usage
* Check language and version selection
* Ensure release includes latest version
* Validate API integration
* **Problem**:
* Editor slow with many keys.
* **Solutions**:
* Use search/filter to narrow view
* Split large namespaces into smaller ones
* Edit in JSON mode for bulk changes
## Next Steps
Learn visual translation mapping
Understand releases management
# Versions
Source: https://docs.unlingo.com/concepts/versions
Understand how versions work in Unlingo to manage different iterations of your translations
## Overview
Versions in Unlingo are containers that hold different iterations of your translations within a namespace. They allow you to organize your translations across different stages of development, maintain multiple versions of your product, and safely manage updates to your content.
Think of versions as branches in version control - each version represents a specific state of your translations that can evolve independently.
## Key Concepts
### Version Structure
Each version contains:
* **Languages**: Multiple language translations
* **Schema**: Content schema for auto syncs
* **Metadata**: Creation time, update history
* **Version Number**: Human-readable identifier
### Version Naming
Versions support flexible naming conventions:
* **Semantic Versioning**: `1.0.0`, `2.1.3`, `1.0.0-beta`
* **Branch Names**: `main`, `develop`, `feature-branch`
* **Environment Names**: `production`, `staging`, `dev`
* **Custom Names**: `winter-release`, `mobile-v1`
## Creating Versions
### New Version
Create a completely new version with no existing content:
1. Navigate to your namespace
2. Click **Create Version**
3. Enter a version number (e.g., `1.0.0`)
4. Leave copy option empty
5. Click **Create Version**
### Copy from Existing Version
Create a new version by copying content from an existing version:
1. Navigate to your namespace
2. Click **Create Version**
3. Enter new version number (e.g., `1.1.0`)
4. Select **Copy from existing version**
5. Choose the source version to copy from
6. Click **Create Version**
Copying from an existing version includes all languages and translations, giving you a complete starting point for
your new version.
## Version Management
### Editing Versions
You can update version names and metadata:
1. Click the **⋮** menu on a version card
2. Select **Edit Version**
3. Update the version name
4. Save changes
Changing version names might break existing releases or API integrations that reference the old name.
### Deleting Versions
To delete a version:
1. Click the **⋮** menu on a version card
2. Select **Edit Version**
3. Click **Delete Version**
4. Confirm the deletion
Deleting a version permanently removes:
* All languages in that version
* All translation data
* Version history and metadata
* Version schema
This action cannot be undone.
## Working with Versions
### Version Workflow
A typical version workflow might look like:
```mermaid
graph LR
A[1.0.0] --> B[1.1.0]
B --> C[1.2.0]
A --> D[1.0.1]
B --> E[2.0.0-beta]
E --> F[2.0.0]
```
1. **Start with base version**: `1.0.0` with core translations
2. **Create feature versions**: `1.1.0` with new features
3. **Maintain patches**: `1.0.1` for critical fixes
4. **Develop major versions**: `2.0.0-beta` for major changes
Version are not connected between each other. They are independent units that can be used for different purposes.
### Version Limits
Each workspace has limits on versions per namespace:
* **Free Plan**: 5 versions per namespace
* **Pro Plan**: 20 versions per namespace
* **Enterprise**: Custom quotas
Monitor your version usage in the namespace header. When approaching limits, consider cleaning up old versions or
upgrading your plan.
## Troubleshooting
* **Problem**:
* Cannot create new versions due to workspace limits.
* **Solutions**:
* Delete unused old versions
* Upgrade workspace plan
* **Problem**:
* Version name already exists.
* **Solutions**:
* Use different naming convention
* Add suffix like `-v2` or `-new`
* Delete conflicting version if no longer needed
* Use semantic versioning to avoid conflicts
* **Problem**:
* Not all translations copied to new version.
* **Solutions**:
* Ensure source version has all expected languages
* Check if copy operation completed successfully
* Verify workspace permissions
* Copy individual languages manually if needed
* **Problem**:
* API returns error for version.
* **Solutions**:
* Verify version exists in namespace
* Check version name spelling
* Ensure API key has access to namespace
## Next Steps
Understand how to publish versions as releases
Deep dive into translation management
# i18next
Source: https://docs.unlingo.com/integrations/i18next
Integrate Unlingo with React applications using i18next for powerful internationalization
## Overview
This guide shows how to integrate Unlingo with React applications using i18next, one of the most popular internationalization frameworks. You'll learn how to set up a custom backend that fetches translations from Unlingo and integrates seamlessly with i18next.
## Prerequisites
* React application
* Basic knowledge of React hooks
* An Unlingo project with translations
## Installation
Install the required dependencies:
```bash npm
npm install i18next react-i18next
```
```bash yarn
yarn add i18next react-i18next
```
```bash pnpm
pnpm add i18next react-i18next
```
## Setting Up the Unlingo Backend
Create a custom i18next backend that fetches translations from Unlingo:
```javascript unlingo-backend.js
class UnlingoBackend {
constructor() {
this.type = 'backend';
// You can add own options if needed
this.init();
}
init() {}
async read(language, namespace, callback) {
try {
const url = new URL('/v1/translations', 'https://api.unlingo.com');
url.searchParams.set('release', process.env.UNLINGO_RELEASE_TAG);
url.searchParams.set('namespace', namespace);
url.searchParams.set('lang', language);
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'x-api-key': process.env.UNLINGO_API_KEY,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
return callback(new Error(`HTTP ${response.status}: ${errorData.error || response.statusText}`), null);
}
const data = await response.json();
callback(null, data);
} catch (error) {
console.error('Unlingo Backend Error:', error);
callback(error, null);
}
}
}
export default UnlingoBackend;
```
```typescript unlingo-backend.ts
import { BackendModule, ReadCallback } from 'i18next';
class UnlingoBackend implements BackendModule {
static type = 'backend' as const;
type = 'backend' as const;
constructor() {
// You can add own options if needed
this.init();
}
init() {}
async read(language: string, namespace: string, callback: ReadCallback) {
try {
const url = new URL('/v1/translations', 'https://api.unlingo.com');
url.searchParams.set('release', process.env.UNLINGO_RELEASE_TAG);
url.searchParams.set('namespace', namespace);
url.searchParams.set('lang', language);
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'x-api-key': process.env.UNLINGO_API_KEY,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
return callback(new Error(`HTTP ${response.status}: ${errorData.error || response.statusText}`), null);
}
const data = await response.json();
callback(null, data);
} catch (error) {
console.error('Unlingo Backend Error:', error);
callback(error as Error, null);
}
}
}
export default UnlingoBackend;
```
## Configuring i18next
Set up i18next with the Unlingo backend:
```javascript i18n.js
import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import UnlingoBackend from './unlingo-backend';
i18next.use(UnlingoBackend).use(initReactI18next).init({
lng: 'en',
fallbackLng: 'en',
});
export default i18next;
```
```typescript i18n.ts
import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import UnlingoBackend from './unlingo-backend';
i18next.use(UnlingoBackend).use(initReactI18next).init({
lng: 'en',
fallbackLng: 'en',
});
export default i18next;
```
## Environment Variables
Add your Unlingo credentials to your environment file:
```env .env.local
UNLINGO_API_KEY=your_api_key_here
UNLINGO_RELEASE_TAG=1.0.0
```
## Initializing in Your App
Import and initialize i18next in your main App component:
```javascript App.js
import React, { Suspense } from 'react';
import './i18n'; // Import i18n configuration
import MainApp from './MainApp';
function App() {
return (
Loading translations...}>
);
}
export default App;
```
```typescript App.tsx
import React, { Suspense } from 'react';
import './i18n';
import MainApp from './MainApp';
const App: React.FC = () => {
return (
Loading translations...}>
);
};
export default App;
```
## Next Steps
Integrate applications with next-intl
Explore the API reference
# next-intl
Source: https://docs.unlingo.com/integrations/next-intl
Integrate Unlingo with Next.js applications using next-intl
## Overview
This guide shows how to integrate Unlingo with Next.js applications using next-intl.
## Prerequisites
* Next.js 13+ application
* Basic knowledge of Next.js
* An Unlingo project with translations
## Installation
Install the required dependencies:
```bash npm
npm install next-intl
```
```bash yarn
yarn add next-intl
```
```bash pnpm
pnpm add next-intl
```
## Project Structure
Set up your Next.js project structure for internationalization:
```
src/
├── app/
│ ├── [locale]/
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── dashboard/
│ │ └── page.tsx
│ └── layout.tsx
├── i18n/
│ ├── request.ts
│ └── routing.ts
└── middleware.ts
```
## Routing Configuration
Configure your locales and routing:
```typescript i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
export const routing = defineRouting({
// A list of all locales that are supported
locales: ['en', 'es', 'fr', 'de'],
// Used when no locale matches
defaultLocale: 'en',
});
```
```javascript i18n/routing.js
import { defineRouting } from 'next-intl/routing';
export const routing = defineRouting({
// A list of all locales that are supported
locales: ['en', 'es', 'fr', 'de'],
// Used when no locale matches
defaultLocale: 'en',
});
```
## Request Configuration
Create a request configuration that fetches translations from Unlingo:
```typescript i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
// This typically corresponds to the `[locale]` segment
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
try {
// Fetch translations from Unlingo
const url = new URL('/v1/translations', 'https://api.unlingo.com');
url.searchParams.set('release', process.env.UNLINGO_RELEASE_TAG);
url.searchParams.set('namespace', process.env.UNLINGO_NAMESPACE);
url.searchParams.set('lang', locale);
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.UNLINGO_API_KEY}`,
'Content-Type': 'application/json',
},
// Cache for 5 minutes
next: { revalidate: 300 },
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const messages = await response.json();
return {
locale,
messages,
};
} catch (error) {
console.error('Failed to load translations:', error);
// Fallback to empty messages or default translations
return {
locale,
messages: {},
};
}
});
```
```javascript i18n/request.js
import { getRequestConfig } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
try {
// Fetch translations from Unlingo
const url = new URL('/v1/translations', 'https://api.unlingo.com');
url.searchParams.set('release', process.env.UNLINGO_RELEASE_TAG);
url.searchParams.set('namespace', process.env.UNLINGO_NAMESPACE);
url.searchParams.set('lang', locale);
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.UNLINGO_API_KEY}`,
'Content-Type': 'application/json',
},
// Cache for 5 minutes
next: { revalidate: 300 },
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const messages = await response.json();
return {
locale,
messages,
};
} catch (error) {
console.error('Failed to load translations:', error);
return {
locale,
messages: {},
};
}
});
```
## Environment Variables
Add your Unlingo credentials to your environment file:
```env .env.local
UNLINGO_API_KEY=your_api_key_here
UNLINGO_RELEASE_TAG=1.0.0
UNLINGO_NAMESPACE=translation
```
## Middleware Configuration
Set up middleware to handle locale detection and routing:
```typescript middleware.ts
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';
export default createMiddleware(routing);
export const config = {
// Match only internationalized pathnames
matcher: ['/', '/(de|en|es|fr)/:path*'],
};
```
```javascript middleware.js
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';
export default createMiddleware(routing);
export const config = {
// Match only internationalized pathnames
matcher: ['/', '/(de|en|es|fr)/:path*'],
};
```
## Next.js Configuration
Update your `next.config.js` to include the internationalization plugin:
```javascript next.config.js
const withNextIntl = require('next-intl/plugin')(
// This is the default (also the `src` folder is supported out of the box)
'./src/i18n/request.ts'
);
module.exports = withNextIntl({
// Other Next.js configuration
});
```
```typescript next.config.ts
import withNextIntl from 'next-intl/plugin';
const withNextIntlConfig = withNextIntl('./src/i18n/request.ts');
export default withNextIntlConfig({
// Other Next.js configuration
});
```
## Root Layout
Set up the root layout:
```typescript src/app/layout.tsx
import { ReactNode } from 'react';
type Props = {
children: ReactNode;
};
// Since we have a `not-found.tsx` page on the root, a layout file
// is required, even if it's just passing children through.
export default function RootLayout({ children }: Props) {
return children;
}
```
```javascript src/app/layout.js
// Since we have a `not-found.tsx` page on the root, a layout file
// is required, even if it's just passing children through.
export default function RootLayout({ children }) {
return children;
}
```
## Locale Layout
Create a layout for your localized pages:
```typescript src/app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
import { notFound } from 'next/navigation';
import { routing } from '@/i18n/routing';
export default async function LocaleLayout({
children,
params: { locale }
}: {
children: React.ReactNode;
params: { locale: string };
}) {
// Ensure that the incoming `locale` is valid
if (!routing.locales.includes(locale as any)) {
notFound();
}
// Providing all messages to the client
// side is the easiest way to get started
const messages = await getMessages();
return (
{children}
);
}
```
```javascript src/app/[locale]/layout.js
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
import { notFound } from 'next/navigation';
import { routing } from '@/i18n/routing';
export default async function LocaleLayout({ children, params: { locale } }) {
// Ensure that the incoming `locale` is valid
if (!routing.locales.includes(locale)) {
notFound();
}
// Providing all messages to the client
// side is the easiest way to get started
const messages = await getMessages();
return (
{children}
);
}
```
## Using Translations in Server Components
### Basic Usage
```typescript src/app/[locale]/page.tsx
import { getTranslations } from 'next-intl/server';
export default async function HomePage() {
const t = await getTranslations('common');
return (
{t('welcome')}
{t('description')}
);
}
```
```javascript src/app/[locale]/page.js
import { getTranslations } from 'next-intl/server';
export default async function HomePage() {
const t = await getTranslations('common');
return (
{t('welcome')}
{t('description')}
);
}
```
### With Interpolation
```typescript
import { getTranslations } from 'next-intl/server';
export default async function UserPage({ params }: { params: { userId: string } }) {
const t = await getTranslations('user');
const user = await getUserById(params.userId);
return (
{t('greeting', { name: user.name })}
{t('lastSeen', { date: new Date(user.lastSeen) })}
);
}
```
## Using Translations in Client Components
For client components, use the `useTranslations` hook:
```typescript components/LanguageSwitcher.tsx
'use client';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
export default function LanguageSwitcher() {
const t = useTranslations('common');
const locale = useLocale();
const router = useRouter();
const languages = [
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Español' },
{ code: 'fr', name: 'Français' },
{ code: 'de', name: 'Deutsch' }
];
const changeLanguage = (newLocale: string) => {
router.push(`/${newLocale}`);
};
return (
);
}
```
## Advanced Features
### Multiple Namespaces
Configure multiple namespaces in your request configuration:
```typescript
// Enhanced i18n/request.ts
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
const namespaces = ['common', 'navigation', 'dashboard', 'auth'];
const messages = {};
// Fetch all namespaces in parallel
await Promise.all(
namespaces.map(async namespace => {
try {
const url = new URL('/v1/translations', 'https://api.unlingo.com');
url.searchParams.set('release', process.env.UNLINGO_RELEASE_TAG);
url.searchParams.set('namespace', namespace);
url.searchParams.set('lang', locale);
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.UNLINGO_API_KEY}`,
'Content-Type': 'application/json',
},
next: { revalidate: 300 },
});
if (response.ok) {
const namespaceMessages = await response.json();
messages[namespace] = namespaceMessages;
}
} catch (error) {
console.error(`Failed to load ${namespace} namespace:`, error);
messages[namespace] = {};
}
})
);
return {
locale,
messages,
};
});
```
## Next Steps
Integrate applications using i18next
Explore the API reference
# Introduction
Source: https://docs.unlingo.com/introduction
Welcome to Unlingo - The modern translation management platform for developers
## What is Unlingo?
Unlingo is a modern, developer-friendly translation management platform designed to simplify internationalization for web and mobile applications. Built with performance and developer experience in mind, Unlingo provides a seamless way to manage, deliver, and scale your application's translations globally.
## Key Features
Instantly propagates translation keys across all languages when you edit the primary language
Simple, intuitive API that developers love to work with
Maintain multiple versions of your translations
Smart caching system that optimizes performance automatically
## How It Works
Unlingo follows a simple, intuitive workflow:
1. **Create Projects & Namespaces**: Organize your translations into logical groups
2. **Upload Translations**: Add your translation keys and values through our dashboard
3. **Create Releases**: Package your translations into versioned releases
4. **Integrate**: Use our API to fetch translations in your application
5. **Enjoy**: Your translations are automatically distributed
Unlingo is designed to work with your existing translation workflow. You can import existing translations and start
using the platform immediately.
## Community & Support
Join our Discord server for real-time help and community discussions
Get in touch with our support team for any questions or issues
## What's Next?
Set up your first project and start translating
Explore our API documentation
# Quickstart
Source: https://docs.unlingo.com/quickstart
Get started with Unlingo in under 5 minutes
## Overview
This quickstart guide will help you set up Unlingo and integrate it into your application in just a few minutes. We'll create a project, add some translations, and fetch them using our REST API.
## Prerequisites
* An Unlingo account (sign up at [unlingo.com](https://unlingo.com/sign-up))
* Basic knowledge of REST APIs
* A web or mobile application project
## Step 1: Create Your Project
Navigate to [unlingo.com](https://unlingo.com/sign-in) and sign in to your account.
Click **Create Project** and enter your project details.
Within your project, create a namespace: - **Name**: "translation" (you can use any name but i18next uses
"translation" by default)
## Step 2: Add New Language
Navigate to your namespaceSelect `main` versionClick **Add language** and enter the language code (e.g., `en`)
## Step 3: Add Translations
Click on the language card
Click **JSON Mode**
Paste your translations in JSON format
```json
{
"welcome": "Welcome to our application",
"login": "Sign In",
"logout": "Sign Out",
"nav": {
"home": "Home",
"about": "About",
"contact": "Contact"
}
}
```
Click **Apply Changes** and Click **Save Changes** in top right corner
## Step 4: Create Your First Release
Go to the **Releases** tab in your project dashboard
Click **Create Release** and enter: - **Tag**: "1.0.0". Select your `translation` namespace and `main` version
Click **Create Release** to make it available via the API
## Step 4: Get Your API Key
Go to the **API Keys** tab in your project dashboardClick **Generate Key** and give it a name like **Production API Key**Copy the generated API key - you'll need it for the next stepSave your key somewhere safe because it will not be shown again.
## Step 5: Fetch Translations
Now you can fetch your translations using our API:
```bash cURL
curl -X GET "https://api.unlingo.com/v1/translations?tag=1.0.0&namespace=translation&lang=en" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```javascript JavaScript/Fetch
const response = await fetch('https://api.unlingo.com/v1/translations?tag=1.0.0&namespace=translation&lang=en', {
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
});
const translations = await response.json();
console.log(translations);
```
Expected response:
```json
{
"translation": {
"welcome": "Welcome to our application",
"login": "Sign In",
"logout": "Sign Out",
"nav": {
"home": "Home",
"about": "About",
"contact": "Contact"
}
}
}
```
## Common Patterns
### Environment-Based Tags
Use different tags for different environments:
```javascript
const tag = process.env.NODE_ENV === 'production' ? '1.0.0' : 'staging';
const translations = await fetch(`https://api.unlingo.com/v1/translations?tag=${tag}&namespace=translation&lang=en`, {
headers: {
Authorization: `Bearer ${process.env.UNLINGO_API_KEY}`,
},
});
```
## Troubleshooting
Make sure your API key is correct. Check that you're using the correct project ID.
**Verify that:**
* Your release is published
* The version, namespace, and language parameters are correct
* Your translations were saved properly in the dashboard
Need help? Join our [Discord](https://discord.gg/TdDYte7KjG) for community support.
## Next Steps
Understand projects
Organize your translations within projects using namespaces
Understand the relationship between versions and releases
Deep dive into translation management