
Security News
Re-Enabled GitHub Actions Expose Thousands of Repositories to Mini Shai-Hulud
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.
@shipi18n/core
Advanced tools
Translation QA for i18n locale files: placeholder and plural validation, key parity, coverage, and an LLM-as-judge semantic review. Also a structure-preserving translation engine — bring your own OpenAI or Anthropic key.
The engine behind Shipi18n's translation QA — placeholder and plural validation, key parity, coverage and an LLM-as-judge semantic review — plus a structure-preserving translation engine. Open source, bring your own LLM, no account and no hosted API.
npm i @shipi18n/core # checking needs nothing else
npm i @shipi18n/core @anthropic-ai/sdk # add a provider SDK to translate or judge
import { runCheck } from '@shipi18n/core'
// deterministic, no model, no key
const { languages, totals } = runCheck({ input: './locales', source: 'en' })
import { translateJSON } from '@shipi18n/core'
const { result, stats } = await translateJSON({
content: { greeting: 'Hello {{name}}', items: 'You have {{count}} items' },
from: 'en',
to: 'es',
provider: 'anthropic', // 'anthropic' | 'openai' | a custom { complete } adapter
apiKey: process.env.ANTHROPIC_API_KEY, // optional — falls back to the provider's env var
})
console.log(result) // { greeting: 'Hola {{name}}', items: 'Tienes {{count}} elementos' }
console.log(stats) // { translated, reused, placeholderWarnings }
The API key is resolved from apiKey or, if omitted, the provider's env var
(ANTHROPIC_API_KEY / OPENAI_API_KEY). Your key is used to call your LLM directly.
The openai provider also takes a baseURL, which points it at any OpenAI-compatible
endpoint — Ollama (http://localhost:11434/v1, no key needed, fully offline), Gemini's
compatibility endpoint, Groq, Mistral, LM Studio, vLLM, or a corporate gateway:
await translateJSON({
content, from: 'en', to: 'es',
provider: 'openai',
baseURL: 'http://localhost:11434/v1', // Ollama — no apiKey required
model: 'llama3.2',
})
{{name}}, {count}, %s, %d, %1$s, $t(...), %{name}, and HTML tags.existing to reuse prior translations and only translate new/changed keys.const { result } = await translateJSON({
content: source, from: 'en', to: 'fr',
provider: 'anthropic',
existing: previousFrench, // only new/empty keys are sent to the LLM
})
Any object with a complete(prompt, opts) => Promise<string> method works — bring any model:
const myAdapter = {
name: 'my-llm',
async complete(prompt) { /* call your model, return its text */ },
}
await translateJSON({ content, from: 'en', to: 'de', provider: myAdapter })
checkTranslations is the QA half of the engine — deterministic, no model call:
import { checkTranslations } from '@shipi18n/core'
const { findings, stats } = checkTranslations({
source: { greeting: 'Hello {{name}}' },
target: { greeting: 'Hola amigo' }, // dropped {{name}}
targetLang: 'es',
})
// findings[0] → { type: 'placeholder-missing', severity: 'error', path: 'greeting', missing: ['{{name}}'], ... }
// stats → { sourceKeys, targetKeys, missing, errors, warnings, coverage }
Finding types: missing-key, orphan-key, placeholder-missing, placeholder-added,
plural-forms (vue-i18n pipe plurals), empty-value, untranslated, type-mismatch.
reviewTranslations({ source, target, from, to, provider, passes, glossary, cache }) is the
semantic layer: an LLM-as-judge pass (BYO key) with majority voting across passes, strict output
validation, and an incremental cache — unchanged pairs cost zero calls. Judge findings carry
{ path, category, note, votes, passes }.
Format adapters are exported too: parseArbBundle (Flutter ARB), parseXcstrings (Apple String
Catalogs), parseAndroidStrings (Android strings.xml), parsePo (gettext .po/.pot) and
parseXliff (XLIFF 1.2/2.0) normalize those files into plain locale objects that checkTranslations
understands — including %@ / %lld specifiers and plural variations.
translateJSON({ content, from, to, provider, apiKey?, model?, baseURL?, existing? }) → { result, stats }translateStrings(texts, { adapter, from, to, batchSize? }) → string[]flatten(obj) / unflatten(flat)extractPlaceholders(str) / validatePlaceholders(source, translation)getLanguageName(code)anthropicAdapter(config) / openaiAdapter(config) / resolveAdapter(provider, config)Apache-2.0
FAQs
Translation QA for i18n locale files: placeholder and plural validation, key parity, coverage, and an LLM-as-judge semantic review. Also a structure-preserving translation engine — bring your own OpenAI or Anthropic key.
The npm package @shipi18n/core receives a total of 0 weekly downloads. As such, @shipi18n/core popularity was classified as not popular.
We found that @shipi18n/core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.

Research
/Security News
A malicious Firefox extension fetches its payload after installation to evade detection, steal Google session cookies, and automate account takeover.

Research
/Security News
The compromise affects MemTensor's MemOS, an open source memory framework for large language models (LLMs) and AI agents. Both npm package @memtensor/memos-cloud-openclaw-plugin and the PyPI package MemoryOS are compromised. They drop cross-platform Go binaries that exfiltrate developer secrets.