I have yet to find a concise, start to finish description of how to create a multilingual WordPress theme.

I am a fairly competent developer and have made a few custom themes in my time. For a project I am working on, I am just starting the process of converting my wireframes into WordPress. I already know that this site will only use this one custom theme I am creating, and I know the site will be available in approximately 5 different languages.

There will be a language selector at the top of the page where the user can simply click the flag of their country and it will refresh some internal setting that will change the language of the whole site. From what I understand, you can use po/mo files to translate sites but I can't get my head around it unfortunately.

The ideal scenario would be for me to develop the theme in English, and for any string that will have multiple translations use some localisation function ( __() & _e() ? ). When development is finished, I need to be able to add a translation to each of the translatable strings for each language. I'm fairly sure the solution is to use POEdit but I can't understand how it all links together.

For clarification, I'm not looking for a plugin where you have different translations for different pages/posts. I'm looking for a solution that lets me translate individual strings within my custom theme.

Thanks in advance to any advice you can give.

2 Answers 2


Daniel's answer was very similar, but applied to plugins rather than themes. For that reason I'll explain how I specifically did it for themes for anyone else who comes across this problem.

  1. Create a folder in the root of your theme called "languages"
  2. Go to https://wpcentral.io/internationalization/, search for your language and copy the "WordPress Locale" code (e.g. cs_CZ for Czech)
  3. Open Poedit
  4. File -> New
  5. Paste the code you coped from wpcentral into the box that appears
  6. Press save, and save to the "languages" folder you created in step 1
  7. Press "Extract from sources" (or Catalogue->Properties)
  8. Under "Sources Paths" press the + on the Paths box
  9. Select your theme folder (e.g. wp-content/themes/my-theme)
  10. In the "Sources Keywords" tab, press "New Item"
  11. Type "__" (underscore underscore, no quotes), and press enter
  12. Type "_e" (no quotes), and press enter
  13. Press OK
  14. Press Save
  15. Press Catalogue->Update from sources
  16. You should see all translatable strings from your theme appear (basically any time you use "__( 'Hello world', 'mydomain' )", the translation will appear)
  17. Once you have completed your translations, press File->Compile to MO (save in the same languages folder from step 1)
  18. Add the following code to the top of your theme's functions file:

    function mytheme_localisation(){
        function mytheme_localised( $locale ) {
            if ( isset( $_GET['l'] ) ) {
                return sanitize_key( $_GET['l'] );
            return $locale;
        add_filter( 'locale', 'mytheme_localised' );
        load_theme_textdomain( 'mytheme', get_template_directory() . '/languages' );
    add_action( 'after_setup_theme', 'mytheme_localisation' );
  19. Now to dynamically translate your site, you can simply add the URL parameter l={language code} (e.g. mysite.com/?l=cs_CZ - this will load the cs_CZ.mo file that we translated using poedit)

To summarise: to translate strings within your theme, use the following code:

__( 'Hello, World!', 'mytheme' )

Where 'mytheme' is the textdomain you set in the function from step 18. Combine this with the creation of the PO/MO files using Poedit and you will be able to make your theme multilingual. In my case this was the perfect solution as I can dynamically change the language using a flag selector on my site, and I can store the user's preference in a cookie, and redirect them when they arrive back.

I hope this helps someone else who has a similar problem, as this took me ages to figure out.

  • Thank you very much, you're a good man. Oct 26, 2021 at 5:27

Myself I have done it a few times in recent year but then only for plug-ins that I made. But I think it will work sort or less the same. You indeed need to use the __() or similar function but also you will always first need to load the text domain. I load the text domain straight after construction of the top class and is initiated explicitly by front and back-end controller descendants to spawn it so this and constants etc are always loaded before further functions execute.

* Init localization text domain
public static function plugin_load_textdomain(){
    load_plugin_textdomain( PLUGIN_TEXTDOMAIN, false, dirname(      
    plugin_basename( __FILE__ ) ) . '/languages' ); 

// This action hooks to WordPress init event and triggers it on init event
add_action( 'init', array($plugin->model, 'plugin_load_textdomain'), 10 ); 

This should work similar with template functions I think. Then use it with a string to translate in view layer ie

<?php echo __( 'Translate me!', PLUGIN_TEXTDOMAIN ); ?>

To make it work the folder plugin_basename( FILE ) ) . '/languages' must contain the PO files with the translated strings. I use Poedit for creating the files. The files created with Poedit are conform the native way WordPress translate and how MO works with WordPress is explained here https://codex.wordpress.org/I18n_for_WordPress_Developers.

Hope this helps and I agree that good info is not much available on this. Feel free to ask more if needed! Gr

  • Thanks very much for your time to write this. I have managed to figure it out now using a fairly similar method, but the key was to, like you say, load the textdomain for the theme. Thanks again!
    – Ollie
    Dec 6, 2016 at 16:54
  • Your welcome and good luck with it! Gr Dec 6, 2016 at 17:50
  • PS use qtranslate next to things you need to translate with above method and your a happy MO camper all the way! Gr Dec 6, 2016 at 17:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.