Lang Forge works well in headless WordPress setups via its REST API and the dynamic lf_language and lf_translations fields.
Building a Multilingual Next.js Site
javascript
// lib/api.js - Lang Forge API client
const API_URL = process.env.WORDPRESS_API_URL;
export async function getLanguages() {
const res = await fetch(`${API_URL}/wp-json/langforge/v1/languages`, {
next: { revalidate: 3600 },
});
if (!res.ok) throw new Error(`Failed to fetch languages: ${res.status}`);
return res.json();
}
export async function getPostsByLanguage(lang, page = 1, perPage = 10) {
const params = new URLSearchParams({
per_page: perPage,
page: page,
meta_key: '_lf_language',
meta_value: lang,
});
const res = await fetch(`${API_URL}/wp-json/wp/v2/posts?${params}`, {
next: { revalidate: 60 },
});
if (!res.ok) throw new Error(`Failed to fetch posts: ${res.status}`);
const posts = await res.json();
const totalPages = parseInt(res.headers.get('X-WP-TotalPages') || '1');
return { posts, totalPages };
}
export async function getTranslationStatus(postType = 'post') {
const res = await fetch(
`${API_URL}/wp-json/langforge/v1/translation-status?post_type=${postType}`
);
if (!res.ok) throw new Error(`Failed to fetch status: ${res.status}`);
return res.json();
}Next.js App Router with i18n Routing
javascript
// app/[lang]/layout.js
import { getLanguages } from '@/lib/api';
export async function generateStaticParams() {
const languages = await getLanguages();
return languages.map(lang => ({ lang: lang.code }));
}
export default async function LangLayout({ children, params }) {
const { lang } = params;
const languages = await getLanguages();
const currentLang = languages.find(l => l.code === lang);
return (
<html lang={currentLang?.locale?.replace('_', '-') || lang}>
<body>
<main>{children}</main>
</body>
</html>
);
}GraphQL Integration (WPGraphQL)
graphql
query GetPost($id: ID!) {
post(id: $id) {
title
content
postMeta {
lfLanguage: metaValue(key: "_lf_language")
}
}
}—