
Craft CMS Multi-Language Setup: Complete Guide
Craft CMS handles multi-language sites differently than most content management systems. Instead of relying on translation plugins, it uses a native multi-site architecture where each language becomes its own site. This approach gives you precise control over what content gets translated and what stays shared across all languages.
This guide walks through the complete setup process from creating sites to implementing language switchers and SEO tags. By the end, you'll have a working multi-language Craft installation with proper content separation and translation workflows. As a comprehensive Craft CMS localization guide, this resource covers everything you need for implementing a multilingual website CMS.
Prerequisites
Before starting, make sure you have:
- Craft CMS 4 or 5 installed and running
- Admin access to Settings → Sites
- Basic familiarity with Twig templating
- A plan for which languages you need
- Decision on URL structure (paths, subdomains, or separate domains)
Note for teams: Site configuration is part of Project Config. Add and configure sites in your development environment, then deploy the config changes. Don't create sites directly in production. Understanding Craft CMS multilingual setup starts with proper environment preparation.
Step 1: Understanding the Architecture
Craft's multi-language system rests on two concepts.
Sites: Each language version of your website is a separate "site" within Craft. A site has its own base URL, language setting, and can have unique content.
Site Groups: Related sites (like all language versions of your main website) belong to a group. Content relationships work within groups, and some propagation settings depend on groups. Understanding Craft CMS site groups is fundamental to Craft CMS multi-site configuration.
For example, a "Main Website" group might contain:
- English (US) (primary site)
- French (France)
- German (Germany)
- Spanish (Spain)
Each site can have a different URL structure:
example.com/en/about (path-based) en.example.com/about (subdomain) example.de/uber-uns (separate domain)
Path-based URLs are the most common choice. They're simpler to manage and keep SEO authority consolidated on one domain.
Step 2: Creating Sites
Go to Settings → Sites and create your sites:
- Create a Site Group (e.g., "Main Website")
- Add your primary site (usually English) with:
- Name: "English (US)"
- Handle: english
- Language: en-US
- Base URL: @web/en/ (using environment variable)
- Mark as Primary: Yes
- Add additional language sites:
- Name: "French"
- Handle: french
- Language: fr-FR
- Base URL: @web/fr/
Repeat for each language. The handle becomes important for template queries later. This completes the initial Craft CMS multi-language site creation.
Craft 5 has a soft cap of 100 sites. For most projects, this is more than enough; typical multi-language builds use 2-15 languages. Craft CMS 5 multi-site capabilities easily accommodate even large international projects.
Step 3: Configuring Section Propagation
Now you need to tell Craft how entries should spread across your sites. Go to Settings → Sections and edit each section.
Propagation Method options:
- All sites: Entry appears in every site automatically
- Site group only: Entry stays within its site group
- Language only: Entry appears in sites with the same language
- Current site only: Entry exists only where created
- Custom: Let editors choose per entry
For most multi-language sites, "All sites" works best. When someone creates a blog post in English, it automatically appears (ready for translation) in French, German, and other sites.
We've found that the "All sites" or "Site group only" options cover 90% of use cases. "Current site only" is useful for region-specific content that shouldn't appear elsewhere. Proper Craft CMS propagation settings ensure content flows correctly between your language sites.
Step 4: Setting Field Translation Methods
This is where many projects go wrong. Creating sites and setting propagation only gets you halfway there. You also need to tell Craft which fields should be translated.
Go to Settings → Fields and set the translation method for each field:
- Not Translatable: Product codes, IDs, dates, anything universal
- Translate for each site: Body text, titles, descriptions, most content fields
- Translate for each site group: Settings that vary between groups but not within
- Translate for each language: Content shared by same-language sites (en-US and en-UK)
Selecting the appropriate Craft CMS field translation method ensures content editors can work independently in each language.
For a typical blog, set your Title and Body fields to "Translate for each site." Leave things like publication date as "Not Translatable."
Matrix blocks add complexity. If your Matrix blocks propagate across sites, you must also configure translation methods for fields inside those blocks. Otherwise, the content stays shared even when you think you're translating. Craft CMS Matrix translation requires this extra attention to detail.
Since Craft 5.3, relation fields (like Assets) also support translation methods. This lets you have different images per language (useful for localized screenshots or culturally appropriate photography).
Step 5: Building the Language Switcher
Here's a Twig template for a language switcher that links to the same entry in different languages:
{% set defined_sites = currentSite.group.sites %}
<ul class="language-switcher">
{% for site in defined_sites %}
{% set defined_entry = entry.id ? craft.entries.id(entry.id).siteId(site.id).one() : null %}
<li>
<a href="{{ defined_entry ? defined_entry.url : site.baseUrl }}"
{% if site.id == currentSite.id %}aria-current="page"{% endif %}>
{{ site.language|slice(0, 2)|upper }}
</a>
</li>
{% endfor %}
</ul>This code gets all sites in the current site's group, loops through each one, finds the equivalent entry in that site (if it exists), and links to the translated entry or falls back to the site's homepage. This Twig multilingual template pattern is the standard approach for Craft CMS language switcher implementations.
Step 6: Adding Hreflang Tags
Search engines need hreflang tags to understand your language structure. Proper Craft CMS hreflang tags are essential for multi-language SEO tags. Add this to your layout template's <head>:
{% for site in currentSite.group.sites %}
{% set defined_entry = entry.id ? craft.entries.id(entry.id).siteId(site.id).one() : null %}
{% if defined_entry %}
<link rel="alternate" hreflang="{{ site.language|replace('_', '-') }}"
href="{{ defined_entry.url }}" />
{% endif %}
{% endfor %}
<link rel="alternate" hreflang="x-default" href="{{ entry.url }}" />The x-default tag tells search engines which version to show when no language match exists. Usually this points to your primary language.
Step 7: Translating Static Strings
Content in entries gets translated through the Craft admin. But what about button labels, menu text, and other UI strings hardcoded in templates?
Wrap these strings with the |t filter:
<button>{{ "Read More"|t }}</button>
<span>{{ "Published on"|t }}</span>Then create translation files in translations/<locale>/site.php:
// translations/fr-FR/site.php
return [
'Read More' => 'Lire la suite',
'Published on' => 'Publié le',
];For teams managing many languages, consider integrating with Crowdin for translation management. Craft has documentation specifically for this workflow. Static string translation in Craft is part of the broader Craft CMS i18n (internationalization) system.
Common Mistakes to Avoid
Forgetting field translation methods. This is the most common issue. Editors switch to French, edit content, and wonder why the English version changed too. The fix: check that content fields are set to "Translate for each site."
Mixing up propagation and translation. Propagation controls whether entries exist across sites. Translation controls whether field values are shared or independent. You need both configured correctly.
Matrix block confusion. Our experience shows that Matrix blocks catch people off guard. If blocks propagate but inner fields aren't set to translate, you end up with shared content that shouldn't be shared.
Missing hreflang on all pages. Hreflang tags should appear on every page, not just the homepage. Make sure your layout template handles entries, category pages, and any custom routes.
Verification Steps
After setup, test your configuration:
- Create a test entry in your primary language
- Switch to another language site and confirm the entry appears
- Edit the entry in the secondary language, and verify the primary language version stays unchanged
- Check the language switcher links to the correct translated URLs
- View page source to confirm hreflang tags are present
- Test date formatting, dates should display in locale-appropriate formats
{# Locale-aware date formatting #}
{{ entry.postDate|date('long') }}
{# English: January 15, 2024 #}
{# French: 15 janvier 2024 #}
{# German: 15. Januar 2024 #}Translation Workflow Options
Craft's built-in workflow has editors translating content directly in the control panel. For more complex needs, consider these plugins:
Multi Translator handles bulk translation using DeepL, Google Cloud Translation, or OpenAI. It works with Matrix and nested content.
Translations by Acclaro integrates with professional translation services for higher-volume projects.
Crowdin integration helps manage large translation projects with external teams.
Machine translation works well for first drafts. Teams we work with often use it to get a starting point, then have human translators refine customer-facing content. A solid Craft CMS translation workflow combines automation with human review for best results.
Conclusion
Building a multi-language site in Craft CMS comes down to understanding three things: sites define your language structure, propagation controls entry availability, and field translation methods determine what gets translated. Get these three configured correctly, and the rest (templates, SEO tags, static strings) follows naturally. Your Craft CMS multi-language implementation will scale smoothly as you add more languages.
The most common hangup is the propagation versus translation distinction. Once that clicks, the system becomes straightforward.
If you're planning a multi-language Craft project and want to validate your architecture before building, we can help you map out the site structure, field configuration, and translation workflow that fits your content team's needs.
