PHP langsys/langsys-php

PHP 基础 SDK:一个客户端适用于任何 PHP 应用——原生 PHP、框架、后台 worker 或 CLI。代码中的短语既是查找键,也是基础语言的默认文本——无需键文件,也无需提取步骤。翻译在服务器端完成,因此页面送达时就已完成本地化。

这是后端 SDK,因此本页面没有浏览器内的演练场——浏览器无法运行 PHP。使用 Laravel?Laravel 软件包通过 Blade 指令、中间件和 Facade 对此客户端进行了封装。完整参考:README。

正在使用 AI 编程智能体?把这段提示词交给它
Add Langsys translation to this PHP app.

1. Read https://docs.langsys.dev/llms.txt, then follow
   https://docs.langsys.dev/learn/sdk/php/ for the install and setup.
2. The English text in the code is the translation key. Wrap user-facing
   strings as they are: no keys file, no extraction step, and no
   hand-written plural or gender branches (Langsys generates those).
3. Read the Langsys project id and API key from environment variables.
   The write key is for development and servers only; anything shipped
   to the browser gets the read-only key.
4. Keep brand names and user-generated content out of translation.

安装

composer require langsys/langsys-php

PHP 7.4 或更高版本,并启用 curl、json 和 intl 扩展——intl 负责为每种语言区域渲染复数形式,并格式化数字和日期。

.env
# A server can hold a WRITE key — it never reaches visitors. A write key is
# what lets phrases your pages use for the first time register themselves.
LANGSYS_API_KEY=your-api-key
LANGSYS_PROJECT_ID=your-project-id

还没有项目或密钥?快速入门两分钟即可帮你搞定。

客户端

每个请求使用一个客户端。它从环境变量中读取凭据,并缓存每种语言区域的目录,因此翻译一个页面最多只需调用一次 API。

查看源码 ↗
<?php
require 'vendor/autoload.php';

use LangsysSDKClient;

// Reads LANGSYS_API_KEY and LANGSYS_PROJECT_ID from the environment.
$langsys = new Client();
$langsys->setLocale('es-es');

翻译

translate() 的第二个参数是语言区域,第三个是类别。将语言区域设为 null 即可使用客户端的当前语言区域。

查看源码 ↗
// translate($phrase, $locale, $category, $contentBlockId, $params)
echo $langsys->translate('Order confirmed', null, 'Checkout');   // current locale
echo $langsys->translate('Order confirmed', 'fr-fr', 'Checkout'); // an explicit one

// A phrase the project doesn't have yet renders as written — never blank.

句子中的值

占位符使用 {name},这是每个 Langsys SDK 存储的相同格式,因此同一份目录在 PHP 后端和 JS 前端渲染的结果完全一致。

查看源码 ↗
// Pass values as params, never build the string yourself.
echo $langsys->translate('Hello, {name}!', null, 'Greetings', null, ['name' => $user->name]);

// sprintf('Hello, %s!', $name) would register "Hello, Sarah!", "Hello, Ahmed!", …
// — one catalog entry per value, billed as words, and impossible to undo.

复数

观看 · 1:14 复数处理

直接写出完整的句子:Langsys 会在翻译过程中生成各语言环境的复数形式,SDK 则会渲染与你的数量相匹配的分支。

查看源码 ↗
// Written flat. Langsys generates each locale's plural forms during
// translation and the SDK picks the branch that matches the count.
echo $langsys->translate('You have {count} new messages.', null, 'Inbox', null, ['count' => $count]);

Langsys 生成的复数形式自 langsys/langsys-php 1.3.2 起才会传递到 PHP;更早的版本对所有数量(包括 1)都会渲染复数形式。

性别一致

西班牙语、法语或俄语会根据所指的人对 {username} has been invited 进行屈折变化。Langsys 会在翻译时生成这些分支(与生成复数形式的方式相同),参数以变量名命名,并加上后缀 _gender:male、female 或 other。只要你知道性别,就请传入。工作原理,以及如何找出需要它的短语 →

传入性别参数 查看源码 ↗
// Pass the agreement argument alongside the value it inflects.
echo $langsys->translate('{username} has been invited', null, 'Team', null, [
    'username'        => $user->name,
    'username_gender' => $user->gender, // 'male' | 'female' | 'other'
]);

不确定性别?请显式传入 'other'——它是中性分支。即使缺少该值,SDK 也会自动为你选择 other 分支,因此句子读起来依然通顺。

分类

类别用于限定短语的范围,因此相同的文字在不同的上下文中可以有不同的译法。

// Same word, two meanings — the category disambiguates.
echo $langsys->translate('Home', null, 'Main Menu');     // es: "Inicio"
echo $langsys->translate('Home', null, 'Home repairs');  // es: "Casa"

访问者的语言区域

可通过你自己的路由或用户设置来指定,也可以让客户端读取浏览器的 Accept-Language 标头。

查看源码 ↗
use LangsysSDKLocaleLocaleDetector;

// Explicit, from your own routing or the user's settings:
$langsys->setLocale('pt-br');

// Or from the browser: without setLocale(), getLocale() reads Accept-Language
// and falls back to the project's base locale.
$locale = $langsys->getLocale();

// The same detection, from a header your framework hands you:
$locale = LocaleDetector::fromAcceptLanguage($request->getHeaderLine('Accept-Language'));

在您的模板中

一个小型辅助函数可以为你的视图提供简短的名称,并对输出进行转义。

helpers.php
<?php
// helpers.php — one client per request, one short name in your templates.
use LangsysSDKClient;

function t(string $phrase, string $category, array $params = []): string
{
    static $langsys = null;
    $langsys ??= (new Client())->setLocale($_SESSION['locale'] ?? 'en-us');

    return htmlspecialchars($langsys->translate($phrase, null, $category, null, $params));
}

// In a template:
// <h1><?= t('Welcome to our store', 'Home') ?></h1>

在服务器端发现词条

使用写入密钥时,项目中尚未见过的每个短语都会在渲染时加入队列,并在响应之后完成注册——访客会立即看到您的基础语言文本,而该短语会被翻译,供下一位访客使用。使用只读密钥时,不会注册任何内容,也不会出现任何问题。

查看源码 ↗
// With a write key, translate() queues every phrase the project doesn't have
// and sends them after the response, from a shutdown handler. Nothing to call.
// With a read key the queue is simply dropped — no errors.

// Or register up front, e.g. from a deploy script:
$langsys->registerPhrases([
    ['phrase' => 'Order confirmed', 'category' => 'Checkout'],
    ['phrase' => 'Copyright 2026', 'category' => 'Footer', 'translatable' => false],
]);

整页内容

已经有 HTML 字符串形式的页面了?一次性翻译完成,连 head 部分也包括在内。

查看源码 ↗
// An HTML page you already have as a string: <title>, meta and OpenGraph
// tags, and the body — phrases and content blocks — in one pass.
ob_start();
// … your app renders the page …
$html = ob_get_clean();

echo $langsys->setLocale('es-es')->translatePage($html, 'Home');

缓存

查看源码 ↗
// Catalogs are cached for an hour (a file cache by default; Redis or none
// via LANGSYS_CACHE_DRIVER). After editing translations in the dashboard:
$langsys->clearCache('es-es');
搜索文档和学习中心