|
| 1 | +# Snippets & Examples |
| 2 | + |
| 3 | +A collection of small, focused recipes that show how to integrate the |
| 4 | +Multisite Language Switcher into a theme or another plugin. The first three |
| 5 | +mirror the canonical examples published on |
| 6 | +[msls.co](https://msls.co/developer-docs/snippets-examples/); the rest are |
| 7 | +short worked examples for the public API functions in |
| 8 | +[`docs/api.md`](api.md) and the hooks in [`docs/hooks.md`](hooks.md). |
| 9 | + |
| 10 | +Each snippet is intentionally minimal. Treat it as a starting point: copy it |
| 11 | +into your `functions.php` or a small mu-plugin, then adapt it to your theme |
| 12 | +locations, post types, and locales. |
| 13 | + |
| 14 | +## Get the current language |
| 15 | + |
| 16 | +In most cases you should use the WordPress function `get_locale()` when you |
| 17 | +need the language of the current blog. MSLS exposes a near-equivalent through |
| 18 | +its blog collection — with the bonus of falling back to `en_US` when the |
| 19 | +value is empty — and gives you the two-letter alpha-2 code as a separate |
| 20 | +accessor. |
| 21 | + |
| 22 | +```php |
| 23 | +$blog = msls_blog_collection()->get_current_blog(); |
| 24 | +$language = $blog->get_language(); // en_US |
| 25 | +$alpha2 = $blog->get_alpha2(); // en |
| 26 | +``` |
| 27 | + |
| 28 | +## Manipulate the nav menu |
| 29 | + |
| 30 | +The `Frontend\Output` class is the right entry point when you want to inject |
| 31 | +the language switcher into a navigation menu. The example below renders the |
| 32 | +links as flag-only items and appends them to the primary menu only. |
| 33 | + |
| 34 | +It's safer to gate on the existence of `msls_output()` than to reference the |
| 35 | +class directly — that way the theme degrades gracefully when MSLS is |
| 36 | +deactivated. |
| 37 | + |
| 38 | +```php |
| 39 | +function my_custom_menu_item( $items, $args ) { |
| 40 | + if ( function_exists( 'msls_output' ) && 'primary' === $args->theme_location ) { |
| 41 | + $arr = msls_output()->get( 2 ); |
| 42 | + if ( ! empty( $arr ) ) { |
| 43 | + $items .= '<li>' . implode( '</li><li>', $arr ) . '</li>'; |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + return $items; |
| 48 | +} |
| 49 | +add_filter( 'wp_nav_menu_items', 'my_custom_menu_item', 10, 2 ); |
| 50 | +``` |
| 51 | + |
| 52 | +The integer passed to `get()` selects the link variant: |
| 53 | + |
| 54 | +```php |
| 55 | +/* Link – flag image plus text */ |
| 56 | +$arr = $obj->get( 0 ); |
| 57 | + |
| 58 | +/* TextOnly – just the language text */ |
| 59 | +$arr = $obj->get( 1 ); |
| 60 | + |
| 61 | +/* ImageOnly – just the flag image */ |
| 62 | +$arr = $obj->get( 2 ); |
| 63 | + |
| 64 | +/* TextImage – text label plus flag image */ |
| 65 | +$arr = $obj->get( 3 ); |
| 66 | +``` |
| 67 | + |
| 68 | +## Iterate the blog collection |
| 69 | + |
| 70 | +When you need to do something for every blog the plugin tracks — emit |
| 71 | +alternate links, build a custom menu, populate a sitemap — iterate the |
| 72 | +collection directly: |
| 73 | + |
| 74 | +```php |
| 75 | +function my_print_something() { |
| 76 | + foreach ( msls_blog_collection()->get() as $blog ) { |
| 77 | + printf( |
| 78 | + '<link rel="alternate" hreflang="%1$s" href="http://%1$s.example.com/" />', |
| 79 | + $blog->get_language() |
| 80 | + ); |
| 81 | + } |
| 82 | +} |
| 83 | +add_action( 'wp_head', 'my_print_something' ); |
| 84 | +``` |
| 85 | + |
| 86 | +Note that `msls_blog_collection()->get()` returns every blog except the |
| 87 | +current one. Use `->get_objects()` instead if you need the full list. |
| 88 | + |
| 89 | +## Render the switcher in a template |
| 90 | + |
| 91 | +The single-line drop-in for theme files. Wrap it in a `function_exists()` |
| 92 | +guard so the template still renders if the plugin is disabled. |
| 93 | + |
| 94 | +```php |
| 95 | +if ( function_exists( 'msls_the_switcher' ) ) { |
| 96 | + msls_the_switcher(); |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +To capture the markup as a string — for example to embed it in another |
| 101 | +component — use `msls_get_switcher()` and forward optional tag overrides: |
| 102 | + |
| 103 | +```php |
| 104 | +$markup = msls_get_switcher( |
| 105 | + array( |
| 106 | + 'before_output' => '<ul class="lang">', |
| 107 | + 'after_output' => '</ul>', |
| 108 | + 'before_item' => '<li>', |
| 109 | + 'after_item' => '</li>', |
| 110 | + ) |
| 111 | +); |
| 112 | +``` |
| 113 | + |
| 114 | +## Link to a single translation |
| 115 | + |
| 116 | +Use `msls_get_permalink()` when you want to build your own switcher markup or |
| 117 | +a single direct link to one specific language. The optional second argument |
| 118 | +is returned when no translation is available, which makes the call safe to |
| 119 | +embed inline: |
| 120 | + |
| 121 | +```php |
| 122 | +$de_url = msls_get_permalink( 'de_DE', home_url( '/' ) ); |
| 123 | +echo '<a href="' . esc_url( $de_url ) . '">Deutsche Version</a>'; |
| 124 | +``` |
| 125 | + |
| 126 | +## Customize the hreflang value |
| 127 | + |
| 128 | +`msls_head_hreflang` filters the value of the `hreflang` attribute generated |
| 129 | +in `<head>`. Use it to enforce a regional locale (for example `en-GB` |
| 130 | +instead of plain `en`) for SEO purposes: |
| 131 | + |
| 132 | +```php |
| 133 | +add_filter( 'msls_head_hreflang', function ( $language ) { |
| 134 | + return 'en_US' === $language ? 'en-US' : $language; |
| 135 | +} ); |
| 136 | +``` |
| 137 | + |
| 138 | +## Restrict supported post types |
| 139 | + |
| 140 | +By default MSLS treats every public post type as translatable. The |
| 141 | +`msls_supported_post_types` filter lets you opt specific post types out — for |
| 142 | +example a `feedback` CPT that you keep mono-lingual: |
| 143 | + |
| 144 | +```php |
| 145 | +add_filter( 'msls_supported_post_types', function ( array $types ): array { |
| 146 | + return array_values( array_diff( $types, array( 'feedback' ) ) ); |
| 147 | +} ); |
| 148 | +``` |
| 149 | + |
| 150 | +The corresponding `msls_supported_taxonomies` filter does the same for |
| 151 | +taxonomies. |
| 152 | + |
| 153 | +## Override the per-language link markup |
| 154 | + |
| 155 | +`msls_output_get` runs for every rendered language item just before it joins |
| 156 | +the output array. The example adds an `aria-current="true"` attribute when |
| 157 | +the item points at the current blog and otherwise leaves the markup alone: |
| 158 | + |
| 159 | +```php |
| 160 | +add_filter( 'msls_output_get', function ( string $url, $link, bool $is_current_blog ): string { |
| 161 | + $current_attr = $is_current_blog ? ' aria-current="true"' : ''; |
| 162 | + |
| 163 | + return sprintf( '<a href="%s" hreflang="%s"%s>%s</a>', |
| 164 | + esc_url( $url ), |
| 165 | + esc_attr( $link->get_language() ), |
| 166 | + $current_attr, |
| 167 | + esc_html( (string) $link ) |
| 168 | + ); |
| 169 | +}, 10, 3 ); |
| 170 | +``` |
| 171 | + |
| 172 | +## Set the status of REST-created translations |
| 173 | + |
| 174 | +The Quick Create REST endpoint inserts new translations as drafts by |
| 175 | +default. Hook `msls_quick_create_post_data` to inherit the source post's |
| 176 | +status instead: |
| 177 | + |
| 178 | +```php |
| 179 | +add_filter( 'msls_quick_create_post_data', function ( array $post_data, \WP_Post $source ): array { |
| 180 | + $post_data['post_status'] = $source->post_status; |
| 181 | + |
| 182 | + return $post_data; |
| 183 | +}, 10, 2 ); |
| 184 | +``` |
| 185 | + |
| 186 | +Remember that any custom callback runs alongside the built-in |
| 187 | +`Msls::prefix_source_language()` filter, which prepends the source locale to |
| 188 | +the new post's title. Remove it with `remove_filter()` if that behavior is |
| 189 | +unwanted in your workflow. |
| 190 | + |
| 191 | +## See also |
| 192 | + |
| 193 | +- [Public API Functions](api.md) — the full reference for every `msls_*` |
| 194 | + helper. |
| 195 | +- [Hooks Reference](hooks.md) — the full list of actions and filters the |
| 196 | + plugin emits. |
0 commit comments