I have one custom taxonomy with countries and states. I'd like to make these terms translatable but I'm not sure what would be the best way to achieve this. First of all, I don't want the slugs to change, only the label, and maybe the description strings.

I thought of two ways. One could be using WPML. But WPML seems to force you change the slug for each language as well which is what I don't want. Another could be wp_insert_term() but I'm not sure if that is efficient or the correct way of doing it. I'd find more practical to let admins/editors to add their own terms, hard coding all the terms wouldn't allow me to do that and furthermore I have a feeling it's not very efficient (there could be a few hundred locations in my taxonomy)...

Any clues?


I contacted WPML support, they explained WPML creates new taxonomy terms for each language and as such each term must have an unique slug... however I'm wondering if there's any other option to achieve this, eg. with term aliases for instance

UPDATE 2 : wp_insert_term()

I found this: http://tommcfarlin.com/programmatically-create-categories/ and it suggests to run wp_insert_term() within a hook of 'after_theme_setup' or after_switch_theme action. However that won't solve the translation problem. Since the hook action fires only after theme setup, even if I gettext all the terms labels strings, it will only consider the language at the moment of theme setup.

  • How did you set up your translatable site in the first place? The answer depends very much on your general site structure.
    – fischi
    Mar 5, 2014 at 0:21
  • Using gettext for theme and other php/js strings - and normally I'd use WPML to manage user content. I was hoping to solve this by gettext. WPML can create new terms and map them to a certain language. However the guys at WPML told me that there's a limitation in WordPress that slugs need to be unique, so a new term has to have a new slug as well. Sometimes this is not elegant, because it may happen that different languages may use the same name and I didn't want to end up with slugs like 'name-2' or 'name-[lang_code]'. I've read that taxonomies support aliases, but didn't dig much further.
    – unfulvio
    Mar 5, 2014 at 3:09

3 Answers 3


I'm not really up to date on WPML and how it handles translations, but my general understanding is that in most cases it simply creates duplicate entries for each language and links them together with the "original".

However, I recently hade a similar problem where I needed the ability to add a "pluralized" version of the term names (as opposed to the default field where I types the name in singular). I solved this by hooking onto <taxonomy>_add_form_fields, <taxonomy>_edit_form_fields, edited_<taxonomy> and create_<taxonomy>.

Solution #1 - add custom taxonomy field

define('TERM_PLURAL_NAME_KEY', 'term_name_plural');

function setup_taxonomies() {
    $taxonomy_name = 'my_tax';

    add_action( $taxonomy_name . '_add_form_fields', 'my_tax_add_plural_name_field', 10, 2 );
    add_action( $taxonomy_name . '_edit_form_fields', 'my_tax_edit_plural_name_field', 10, 2 );

    add_action( 'edited_' . $taxonomy_name, 'save_my_tax_meta', 10, 2 );
    add_action( 'create_' . $taxonomy_name, 'save_my_tax_meta', 10, 2 );
add_action('init', 'setup_plural_taxonomies')

function my_tax_add_plural_name_field() {
        <div class="form-field">
            <label for="term_meta[<?php echo TERM_PLURAL_NAME_KEY; ?>]"><?php _e( 'Plural name', 'i18n_key' ); ?></label>
            <input type="text" name="term_meta[<?php echo TERM_PLURAL_NAME_KEY; ?>]" id="term_meta[<?php echo TERM_PLURAL_NAME_KEY; ?>]" value="">
            <p class="description"><?php _e( 'A pluralized version of the term title, to be used when multiple objects are referred to.', 'i18n_key' ); ?></p>

function my_tax_edit_plural_name_field($term) {
        $t_id = $term->term_id;
        $term_meta = get_option( "taxonomy_$t_id" ); ?>
        <tr class="form-field">
        <th scope="row" valign="top"><label for="term_meta[<?php echo TERM_PLURAL_NAME_KEY; ?>]"><?php _e( 'Plural name', 'i18n_key' ); ?></label></th>
                <input type="text" name="term_meta[<?php echo TERM_PLURAL_NAME_KEY; ?>]" id="term_meta[<?php echo TERM_PLURAL_NAME_KEY; ?>]" value="<?php echo esc_attr( $term_meta[TERM_PLURAL_NAME_KEY] ) ? esc_attr( $term_meta[TERM_PLURAL_NAME_KEY] ) : ''; ?>">
                <p class="description"><?php _e( 'A pluralized version of the term title, to be used when multiple objects are referred to.', 'i18n_key' ); ?></p>

function save_my_tax_meta($term_id) {
    if ( isset( $_POST['term_meta'] ) ) {
        $t_id = $term_id;
        $term_meta = get_option( "taxonomy_$t_id" );
        $cat_keys = array_keys( $_POST['term_meta'] );
        foreach ( $cat_keys as $key ) {
            if ( isset ( $_POST['term_meta'][$key] ) ) {
                $term_meta[$key] = $_POST['term_meta'][$key];
        update_option( "taxonomy_$t_id", $term_meta );

The above code could easily be modified to hold a localized string instead of the name in plural. You could then loop through the list of activated languages in WPML, and a a field for each language (you'd need to adjust all the functions above). This might be impractical though if you have a lot of languages enabled in WPML and might very well clutter the editor.

Which is why I could also imagine an alternate implementation...

Solution #2 - Connect "localized" terms with "default language" term

Not sure if WPML would do this automatically for you, but in case it does not you could let it create localized terms for each language, and write a function that, given a term, returns the localized language instance of the that term. You could then create this relation using the same hooks as in the example above, but instead adding two fields - the first holding the default language version of the term (using wp_dropdown_categories) and the other being holding the language of the localized term.

As I said, I have little experience with WPML and one could imaging this type of functionality is already implemented in the plugin itself, so I'd suggest investigating that before going down this path.

  • thanks Simon, I think #1 works best; WPML has something close to #2 but creating new terms is probably redundant and furthermore will impose creating new slugs. I will go for option #1.
    – unfulvio
    Mar 10, 2014 at 13:57

You always could add custom fields to terms, each custom field will represent a translation, I've found a good tutorial about this subject, it shows how to add a custom field to the taxonomy edition page.


I'm not sure how you're planning to deal with these terms, but I think you can still use WPML native way to handle terms translations, even though you can't keep the same slug.

When you need to deal with a term slug, you can rely on the icl_object_id() function.

For instance, suppose you have English as default language, and Italian as a second language. You define a term "Rome", with slug "rome". When translating it to "Roma", the slug will become "roma", or "rome-2" if you try to use the same slug.

When you need to work with the current term, you can use something like that:

global $sitepress;

$taxonomy_name = 'cities';
$current_term_slug = 'roma'; //so, that's Italian, for instance;

$current_term = get_term_by( 'slug', $current_term_slug, $taxonomy_name );

//Term exists
if($current_term) {
    $default_language = $sitepress->get_default_language();
    $current_language = $sitepress->get_current_language();

    $term_id = $current_term->term_id;
    if ( $default_language != $current_language ) {
        //Here you get the default language term id
        $term_id = icl_object_id( $term_id, $taxonomy_name, false, $default_language );

That's just an example, but I think it's clear enough to show you how to always convert the slug of a given taxonomy term, to the one defined in the default language.

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.