Framework Reference

Complete public API of the ProjectLocale iOS SDK. All types live in the ProjectLocale module. Import it with import ProjectLocale.

Configuration

L10n.configure(apiKey:serverURL:environment:appVersion:fallbackBundle:logLevel:logHandler:) func throws

Initialize the SDK. Must be called once at app launch before any other method.

  • apiKey: String — your project API key (pl_...), found in project settings
  • serverURL: URL — server URL, e.g. https://p-locale.eu
  • environment: String = "prod" — target environment: dev, qa, or prod
  • appVersion: String? = nil — app version for per-version translations; pass CFBundleShortVersionString
  • fallbackBundle: Bundle = .main — bundle containing fallback .strings files
  • logLevel: LogLevel = .warning — logging verbosity
  • logHandler: LogHandler = defaultLogHandler — custom log output handler
  • realtimeEnabled: Bool = false — enable WebSocket connection for instant translation updates pushed from the server
L10n.configure(_ config: L10n.Configuration) func throws

Alternative initializer using a Configuration struct. Same parameters as above, plus session: URLSession and storageDirectory: URL?.

import ProjectLocale

try L10n.configure(
    apiKey: "pl_your_api_key",
    serverURL: URL(string: "https://p-locale.eu")!,
    environment: "prod",
    appVersion: Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
)

Syncing Translations

L10n.projectInfo() → ProjectInfo func async throws

Fetch project metadata from the server: available languages, environments, and per-version configuration. Usually the first call on launch.

L10n.syncAll() → [String] func async throws

Convenience wrapper: calls projectInfo(), then fetches translations for all languages in parallel. Returns the list of synced locale codes. Removes cached locales that are no longer in the project.

L10n.fetch(locale: String) → Bool func async throws

Download translations for a specific locale. Returns true if new data was applied. Uses delta sync — only changed keys are transferred.

L10n.checkForUpdate(locale: String?) → Bool func async throws

Check for and apply updates for the given locale (defaults to current language). Returns true if translations were updated.

// Sync all languages at once
let synced = try await L10n.syncAll()

// Or sync a specific locale
try await L10n.fetch(locale: "de")

Using Translations

L10n.string(_ key: String, default: String, table: String?) → String func

Resolve a translation key. Keys use the format namespace/key_name. Returns the translation for the current language, or the default value if the key is not found.

  • key: String — full key, e.g. "common/welcome_title"
  • default: String = "" — fallback if the key is missing; if empty, the key itself is returned
  • table: String? = nil — optional table override (defaults to namespace from key)
L10nText(_ key: String, default: String) SwiftUI View

SwiftUI view that displays a translated string. Automatically updates when translations change. Available on iOS 15+.

// SwiftUI
L10nText("common/welcome_title", default: "Welcome")

// Imperative (UIKit, ViewModels, etc.)
let title = L10n.string("common/welcome_title", default: "Welcome")

Language Management

L10n.setLanguage(_ code: String) func

Switch the active language. Triggers L10n.observer so any SwiftUI view observing it will refresh automatically.

L10n.currentLanguage → String property

The currently active language code (BCP-47). Defaults to the device's preferred language.

L10n.availableLanguages → [String] property

List of locale codes for which translations are currently cached locally.

L10n.hasCachedTranslations → Bool property

Returns true if at least one locale has cached translations from a previous session.

Reactivity (Combine)

L10n.observer → TranslationObserver static

A shared ObservableObject that publishes a revision counter every time translations change — whether from a network sync, language switch, or a real-time WebSocket push. Use @ObservedObject in SwiftUI to get automatic UI refresh.

struct MyView: View {
    @ObservedObject private var observer = L10n.observer

    var body: some View {
        let _ = observer.revision
        Text(L10n.string("welcome_title", default: "Welcome"))
    }
}

Real-Time Updates (WebSocket)

realtimeEnabled: Bool = false config

When enabled, the SDK opens a WebSocket connection to the server. Translation changes made in the web UI are pushed to the device instantly — no polling or manual sync required. The connection auto-reconnects with exponential backoff if interrupted.

Updates arrive through the same L10n.observer pipeline, so any SwiftUI view already using @ObservedObject will refresh automatically.

try L10n.configure(
    apiKey: "pl_...",
    serverURL: URL(string: "https://p-locale.eu")!,
    realtimeEnabled: true
)

Diagnostics

L10n.revisionSnapshot() → [String: (appVersion: String, revision: Int)] func

Returns the last-known revision for each cached locale. Useful for debugging sync state. Keys are BCP-47 locale codes.

Types

ProjectInfo struct

Project metadata returned by projectInfo().

  • slug: String — project URL slug
  • name: String — project display name
  • sourceLanguage: String — source language code
  • targetLanguages: [String] — target language codes
  • languages: [String] — all languages (source + target)
  • environments: [String] — available environments
  • environmentsVersions: [EnvironmentVersions]? — per-environment version metadata
  • languages(for:appVersion:) → [String]? — resolve languages for a specific environment and version
LogLevel enum

Logging verbosity levels: .debug, .info, .warning, .error, .critical, .off.

LocaleError enum

Errors thrown by SDK methods.

  • .notConfigured — L10n.configure() was not called
  • .network(underlying:) — network request failed
  • .http(status:body:) — server returned a non-success HTTP status
  • .invalidArchive(reason:) — translation bundle is malformed
  • .invalidManifest(reason:) — manifest data is invalid

Platform Guide

Step-by-step guide to using the Project Locale web platform — from creating a project to delivering translations to your app.

Account & Registration

1

Create an account

Go to p-locale.eu and click Sign up free. Enter your email, username, and password. A verification email will be sent — click the link to activate your account.

2

Choose a plan

The free plan includes 1 project and 2 languages. Upgrade anytime from your Profile page to unlock more projects, languages, team members, and AI translations.

3

Profile settings

In Profile you can change your password, update your email, manage your subscription, and leave projects you've been invited to.

Projects

1

Create a project

Click New project on the dashboard. Enter a name, select a source language, and add target languages. The project slug is generated automatically and used in the API.

2

API key

Each project has a unique API key displayed in the project settings (Edit page). This key is used in the SDK's L10n.configure(apiKey:). You can rotate the key at any time — the old key will stop working immediately.

3

Project settings

From the project edit page you can rename the project, change source/target languages, and delete the project. Deleting a project removes all environments, versions, keys, and translations permanently.

Environments & Versions

1

Environments

Environments separate translations for different stages: dev, qa, prod. Each environment has its own set of app versions. The SDK connects to the environment specified in L10n.configure(environment:).

2

App versions

Inside each environment, you create app versions that match your app releases (e.g. 1.0, 2.0). Each version has its own set of translations, languages, and revision counter. The SDK sends appVersion to get translations for the matching version.

3

Per-version languages

You can configure which target languages are available for each version. This lets you add a new language to v2.0 without affecting v1.0.

Namespaces & Keys

1

Namespaces

Namespaces group related keys together (e.g. common, settings, onboarding). Each version starts with a common namespace. You can create more from the project page.

2

Creating keys

Click Add key on the project page. Enter the key name and select a namespace. The full key path used in code is namespace/key_name.

3

Translation editor

Click any key to open the editor. You'll see all target languages side by side. Edit translations inline — changes are saved immediately. Each translation has a status: draft, translated, reviewed, or approved.

4

Translation statuses

Draft — empty or initial. Translated — text entered. Reviewed — checked by a reviewer. Approved — ready for delivery. Only approved translations are delivered to devices via the SDK.

Import & Export

1

Import .strings

Click Import on the project page. Upload a .strings file, select the target language and namespace. Existing keys will be updated; new keys will be created automatically.

2

Export .strings

Click Export to download translations as a .strings file. Select the language and namespace to export. The file can be used directly in Xcode.

AI Translation

1

Translate a single key

In the translation editor, click the AI button next to any language field. The system will generate a translation based on the source text. Review and approve before it goes live.

2

Batch translate

When you add a new language to a version, you can use AI Batch Translate to translate all existing keys at once. This is available on paid plans.

SDK Integration

1

Install the SDK

Swift Package Manager (recommended): In Xcode, go to File → Add Package Dependencies, enter https://github.com/biometricid/p-locale.eu, select Up to Next Major Version (1.1.0), and click Add Package.

Manual: Go to the SDK page to download ProjectLocale.xcframework. Drag it into your Xcode project with Do Not Embed (static library).

2

Configure and sync

Call L10n.configure() in your app's init() with your API key and server URL. Then call L10n.syncAll() to download translations. See the Framework Reference above for full API details.

3

How delivery works

The SDK caches translations locally. On each app launch, it sends a revision number to the server. If translations changed, only the diff is downloaded (delta sync). If nothing changed, the server responds with 304 Not Modified — zero data transfer. Translations are available offline from cache.