Language Packages

8 vues Markdown

The seven endpoints that see, copy, set up and remove the installed languages.

Overview

A language lives in three places at once in WISECP: the package file (name, country, order, state), the translation files and the language tables holding product names, category titles and notification templates. This article manages the first and the whole.

A new language is never born empty; it is set up by copying one that is installed. The copy takes both the table rows and the file tree, which makes it heavy work.

One language is the default and that one is privileged: it cannot be closed, cannot be removed, and carries no language prefix in its addresses. Moving the default swaps those three behaviours between two languages.

Reference

Listing the Installed Languages

get/api/v1/admin/languages
Languages/GetLanguages admin

Returns every language on the installation, the closed ones included.

Response fields data[] — 15 + meta — 2
keystringThe language key. This is what the addresses carry.
namestringThe language name in English.
show_namestringThe name shown to a client.
codestringThe language code.
code_hyphenstringThe language and country code together.
country_idintThe country id. Look to the reference endpoints for its name.
country_codestringThe country code.
statusboolWhether the language is on.
localboolWhether it is the default. One language on the installation carries this.
rtlboolWhether the language reads right to left.
rankintWhere it sits in the listing.
permalinkboolWhether permalinks are supported.
prefixstringWhere the address prefix stands. Off on the default language and on for the rest.
copiedstringThe name of the language it was copied from.
created_atstringWhen it was made.
countintHow many languages there are. It comes back under meta.
defaultstringThe default language key.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/languages' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/languages', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data, meta } = await res.json();
const live = data.filter((l) => l.status);
$ch = curl_init('https://panel.example.com/api/v1/admin/languages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The closed ones come too; filter on status for the languages open to a client.
$r    = Api::Languages()->GetLanguages();
$live = array_values(array_filter($r['data'], fn ($l) => $l['status']));
$def  = $r['meta']['default'];

Listing What Can Be Downloaded

get/api/v1/admin/languages/available
Languages/GetAvailableLanguages admin a remote service

Returns the languages the WISECP translation service offers.

Response fields data[] + meta — 1
dataobject[]The language definitions the remote service returns. An empty list comes back when the service cannot be reached.
countintHow many came back. It comes back under meta.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/languages/available' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/languages/available', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data, meta } = await res.json();
if (meta.count === 0) showRetry();
$ch = curl_init('https://panel.example.com/api/v1/admin/languages/available');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// AN EMPTY LIST means one of two things: none exist or the remote service failed. They look alike.
$out = Api::Languages()->GetAvailableLanguages();
if (! $out['data']) $logger->warning('empty language list — check the service is reachable');

Reading One Language

get/api/v1/admin/languages/{key}
Languages/GetLanguage admin

Returns one language package.

Response fields data — 15
dataobjectThe language package. Same shape as an item in the listing.
Errors 2
language_not_found404No such language.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/languages/de' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch(`https://panel.example.com/api/v1/admin/languages/${key}`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/languages/' . $key);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The key is not the language CODE: a second country under one code takes the 'en-gb' form.
$pkg = Api::Languages()->GetLanguage(['key' => $key])['data'];

Making a Language by Copying

post/api/v1/admin/languages
Languages/CreateLanguage admin heavy work

Sets up a new language by copying one that is installed.

Body 6
copy_languagestringreqThe key of the language to copy. It has to be installed.
languagestringreqThe new language code. It needs letters; digits alone are turned down.
country_idintreqThe country id.
show_namestringreqThe name to show a client.
rankintWhere it sits in the listing.
rtlintSend 1 when it reads right to left.
Response fields 201 — data — 15
dataobjectThe language package set up. Read its key here; it can differ from the code you sent.
Errors 7
country_required422The country id is missing.
language_required422The language code is empty or all digits.
copy_language_invalid422The source language is not installed.
show_name_required422The display name is empty.
language_exists422That language and country pair is already installed.
copy_tables_failed500The language table rows could not be copied.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/languages' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"copy_language":"en","language":"de","country_id":276,"show_name":"Deutsch"}'
const res = await fetch('https://panel.example.com/api/v1/admin/languages', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    copy_language: 'en',
    language: 'de',
    country_id: 276,
    show_name: 'Deutsch',
    rank: 2,
  }),
});

const { data } = await res.json();
const realKey = data.key;   // 'de' olmayabilir
$ch = curl_init('https://panel.example.com/api/v1/admin/languages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'copy_language' => 'en',
        'language'      => 'de',
        'country_id'    => 276,
        'show_name'     => 'Deutsch',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// When the code you send IS already installed the key becomes 'code-country'; read it, do not assume.
$pkg = Api::Languages()->CreateLanguage([
    'copy_language' => 'en', 'language' => 'en',
    'country_id' => 826, 'show_name' => 'English (UK)',
])['data'];

$key = $pkg['key'];    // 'en-gb'

Changing a Language's Settings

patch/api/v1/admin/languages/{key}
Languages/UpdateLanguage admin promoting is heavy

Changes the fields you send and can promote the language to default.

Body 5
show_namestringThe name shown to a client. It cannot be empty once sent.
rankintWhere it sits in the listing.
rtlintSend 1 when it reads right to left.
statusintWhether the language is on. It is ignored on the default language.
localintSend 1 to make this the default. It changes the address prefix of two languages at once.
Response fields data — 15
dataobjectThe language package as it now stands.
Errors 3
language_not_found404No such language.
show_name_required422The name you sent is empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X PATCH 'https://panel.example.com/api/v1/admin/languages/de' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"show_name":"Deutsch","rank":2}'
const res = await fetch(`https://panel.example.com/api/v1/admin/languages/${key}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ show_name: 'Deutsch', rank: 2 }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/languages/' . $key);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['show_name' => 'Deutsch', 'rank' => 2]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// On the DEFAULT language status is IGNORED: the answer is 200 while the language stays on.
$pkg = Api::Languages()->UpdateLanguage(['key' => $key, 'status' => 0])['data'];
if ($pkg['status']) $logger->info('the default language cannot be closed — nothing changed');

Turning a Language On and Off

put/api/v1/admin/languages/{key}/status
Languages/SetLanguageStatus admin

Opens a language to clients or closes it.

Body 1
statusintreqThe new state: 0 for off and 1 for on.
Response fields data — 2
keystringThe language key.
statusboolWhere it now stands.
Errors 5
language_not_found404No such language.
invalid_status422The state is neither 0 nor 1.
language_is_default422The default language cannot be closed.
no_change422The language already sits in the state you asked for.
insufficient_scope403The key lacks the required scope.
Request
curl -X PUT 'https://panel.example.com/api/v1/admin/languages/de/status' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":1}'
const res = await fetch(`https://panel.example.com/api/v1/admin/languages/${key}/status`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ status: 1 }),
});

if (res.status === 422) { /* zaten aciksa buraya duser */ }
$ch = curl_init('https://panel.example.com/api/v1/admin/languages/' . $key . '/status');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['status' => 1]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Writing the same state again is an ERROR; read the current one first during a bulk sync.
$pkg = Api::Languages()->GetLanguage(['key' => $key])['data'];
if ($pkg['status'] !== $wanted) Api::Languages()->SetLanguageStatus(['key' => $key, 'status' => (int) $wanted]);

Removing a Language

delete/api/v1/admin/languages/{key}
Languages/DeleteLanguage admin cannot be undone

Removes a language, its translations and every row belonging to it.

Response fields data — 2
deletedboolWhether the delete ran.
keystringThe key of the language removed.
Errors 4
language_not_found404No such language.
language_is_default422The default language cannot be removed.
remove_tables_failed500The language table rows could not be removed.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/languages/de' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch(`https://panel.example.com/api/v1/admin/languages/${key}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/languages/' . $key);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The product and category names IN THAT LANGUAGE go as well; export and keep them first.
$dump = Api::Languages()->ExportLanguageTranslations(['key' => $key])['data'];
file_put_contents("backup-$key.json", json_encode($dump));

Api::Languages()->DeleteLanguage(['key' => $key]);

Pitfalls

The key made is not always the code you sent

When the language code you send is already installed, the new key takes the code-country form. Setting up a second English makes en-gb rather than en. Read the key from the answer, since every later call wants it.

Moving the default changes the addresses of two languages

Making a language the default opens the prefix on the old default and closes it on the new one. The public addresses of both languages change and the old links shift. The job also rewrites the settings file and forces the new language open. Do not run it unplanned on a live installation.

Two paths handle one state differently

The status endpoint turns down closing the default language with 422. The settings endpoint ignores the same request quietly and answers 200 while the language stays open. A script mixing the two believes it closed something. Look at the state in the answer.

Writing the same state gives an error

The status endpoint answers 422 with no_change when the state you ask for is the one already there. The endpoint is not repeatable: a sync loop setting every language to open errors on the ones that are open. Read the current state before writing.

Removing takes more than the translations

Removing a language takes the translation files, the notification templates and the language table rows: the product names, category titles and page content in that language go with it. The only way back is a backup. Export the translations first.

An empty download list can mean a failure

The downloadable languages come from a remote service. When it cannot be reached the endpoint raises no error and returns an empty list. That makes "no languages" and "the service failed" look alike. Leave a way to retry before showing an empty result as "nothing to pick".

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Besoin d'aide supplémentaire ?

Notre équipe d'assistance est disponible 24h/24 pour tout ce que vous ne trouvez pas ci-dessus.