@mytechtoday/augment-extensions 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/cli/dist/cli.js +5 -1
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +41 -0
- package/cli/dist/commands/show.js.map +1 -1
- package/modules.md +52 -0
- package/package.json +1 -1
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# Internationalization (i18n)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide covers WordPress plugin internationalization (i18n) and localization (l10n) including text domains, translation functions, pluralization, context, and translation file generation.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Text Domain
|
|
10
|
+
|
|
11
|
+
### Defining Text Domain
|
|
12
|
+
|
|
13
|
+
The text domain must match your plugin slug and be consistent throughout.
|
|
14
|
+
|
|
15
|
+
```php
|
|
16
|
+
<?php
|
|
17
|
+
/**
|
|
18
|
+
* Plugin Name: My Plugin
|
|
19
|
+
* Text Domain: my-plugin
|
|
20
|
+
* Domain Path: /languages
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// Load text domain
|
|
24
|
+
function my_plugin_load_textdomain() {
|
|
25
|
+
load_plugin_textdomain(
|
|
26
|
+
'my-plugin',
|
|
27
|
+
false,
|
|
28
|
+
dirname( plugin_basename( __FILE__ ) ) . '/languages'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
add_action( 'plugins_loaded', 'my_plugin_load_textdomain' );
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Text Domain Rules
|
|
35
|
+
|
|
36
|
+
✅ **DO**:
|
|
37
|
+
- Use lowercase with hyphens: `my-plugin`
|
|
38
|
+
- Match plugin slug exactly
|
|
39
|
+
- Use consistently throughout plugin
|
|
40
|
+
- Define in plugin header
|
|
41
|
+
|
|
42
|
+
❌ **DON'T**:
|
|
43
|
+
- Use underscores: `my_plugin`
|
|
44
|
+
- Use variables for text domain
|
|
45
|
+
- Mix multiple text domains
|
|
46
|
+
- Omit text domain parameter
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Translation Functions
|
|
51
|
+
|
|
52
|
+
### Basic Translation
|
|
53
|
+
|
|
54
|
+
```php
|
|
55
|
+
<?php
|
|
56
|
+
// Translate and return
|
|
57
|
+
$text = __( 'Hello World', 'my-plugin' );
|
|
58
|
+
|
|
59
|
+
// Translate and echo
|
|
60
|
+
_e( 'Hello World', 'my-plugin' );
|
|
61
|
+
|
|
62
|
+
// Translate with escaping (recommended)
|
|
63
|
+
echo esc_html__( 'Hello World', 'my-plugin' );
|
|
64
|
+
esc_html_e( 'Hello World', 'my-plugin' );
|
|
65
|
+
|
|
66
|
+
// Attribute escaping
|
|
67
|
+
echo '<input placeholder="' . esc_attr__( 'Enter name', 'my-plugin' ) . '" />';
|
|
68
|
+
esc_attr_e( 'Enter name', 'my-plugin' );
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Variables in Translations
|
|
72
|
+
|
|
73
|
+
```php
|
|
74
|
+
<?php
|
|
75
|
+
// ✅ CORRECT: Use sprintf
|
|
76
|
+
echo sprintf(
|
|
77
|
+
/* translators: %s: user name */
|
|
78
|
+
__( 'Hello %s', 'my-plugin' ),
|
|
79
|
+
$user_name
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// ✅ CORRECT: Multiple variables
|
|
83
|
+
echo sprintf(
|
|
84
|
+
/* translators: 1: post count, 2: category name */
|
|
85
|
+
__( 'Found %1$d posts in %2$s', 'my-plugin' ),
|
|
86
|
+
$count,
|
|
87
|
+
$category
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// ❌ WRONG: Concatenation breaks translation
|
|
91
|
+
echo __( 'Hello', 'my-plugin' ) . ' ' . $user_name;
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Plural Forms
|
|
95
|
+
|
|
96
|
+
```php
|
|
97
|
+
<?php
|
|
98
|
+
// Basic plural
|
|
99
|
+
echo sprintf(
|
|
100
|
+
_n(
|
|
101
|
+
'One item',
|
|
102
|
+
'%d items',
|
|
103
|
+
$count,
|
|
104
|
+
'my-plugin'
|
|
105
|
+
),
|
|
106
|
+
number_format_i18n( $count )
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// With context
|
|
110
|
+
echo sprintf(
|
|
111
|
+
_n(
|
|
112
|
+
'One comment',
|
|
113
|
+
'%d comments',
|
|
114
|
+
$comment_count,
|
|
115
|
+
'my-plugin'
|
|
116
|
+
),
|
|
117
|
+
number_format_i18n( $comment_count )
|
|
118
|
+
);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Context
|
|
122
|
+
|
|
123
|
+
Use context when the same English word has different meanings:
|
|
124
|
+
|
|
125
|
+
```php
|
|
126
|
+
<?php
|
|
127
|
+
// Noun vs Verb
|
|
128
|
+
_x( 'Post', 'noun', 'my-plugin' );
|
|
129
|
+
_x( 'Post', 'verb', 'my-plugin' );
|
|
130
|
+
|
|
131
|
+
// Different contexts
|
|
132
|
+
_x( 'Read', 'past tense', 'my-plugin' );
|
|
133
|
+
_x( 'Read', 'imperative', 'my-plugin' );
|
|
134
|
+
|
|
135
|
+
// With escaping
|
|
136
|
+
echo esc_html_x( 'Draft', 'post status', 'my-plugin' );
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## JavaScript Translations
|
|
142
|
+
|
|
143
|
+
### wp_set_script_translations()
|
|
144
|
+
|
|
145
|
+
```php
|
|
146
|
+
<?php
|
|
147
|
+
function my_plugin_enqueue_scripts() {
|
|
148
|
+
wp_enqueue_script(
|
|
149
|
+
'my-plugin-script',
|
|
150
|
+
plugins_url( 'js/script.js', __FILE__ ),
|
|
151
|
+
array( 'wp-i18n' ),
|
|
152
|
+
'1.0.0',
|
|
153
|
+
true
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// Set translations for script
|
|
157
|
+
wp_set_script_translations(
|
|
158
|
+
'my-plugin-script',
|
|
159
|
+
'my-plugin',
|
|
160
|
+
plugin_dir_path( __FILE__ ) . 'languages'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue_scripts' );
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### JavaScript Translation Functions
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
// Import i18n
|
|
170
|
+
import { __, _x, _n, sprintf } from '@wordpress/i18n';
|
|
171
|
+
|
|
172
|
+
// Basic translation
|
|
173
|
+
const message = __( 'Hello World', 'my-plugin' );
|
|
174
|
+
|
|
175
|
+
// With context
|
|
176
|
+
const label = _x( 'Post', 'noun', 'my-plugin' );
|
|
177
|
+
|
|
178
|
+
// Plural
|
|
179
|
+
const count = 5;
|
|
180
|
+
const text = sprintf(
|
|
181
|
+
_n( 'One item', '%d items', count, 'my-plugin' ),
|
|
182
|
+
count
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
// With variables
|
|
186
|
+
const greeting = sprintf(
|
|
187
|
+
__( 'Hello %s', 'my-plugin' ),
|
|
188
|
+
userName
|
|
189
|
+
);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Translation File Generation
|
|
195
|
+
|
|
196
|
+
### Using WP-CLI
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Generate POT file
|
|
200
|
+
wp i18n make-pot . languages/my-plugin.pot
|
|
201
|
+
|
|
202
|
+
# Generate JSON for JavaScript
|
|
203
|
+
wp i18n make-json languages --no-purge
|
|
204
|
+
|
|
205
|
+
# Update PO files
|
|
206
|
+
wp i18n update-po languages/my-plugin.pot languages/
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Manual POT Generation
|
|
210
|
+
|
|
211
|
+
Use tools like Poedit or GlotPress to extract translatable strings.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Translation File Structure
|
|
216
|
+
|
|
217
|
+
### Directory Structure
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
my-plugin/
|
|
221
|
+
├── languages/
|
|
222
|
+
│ ├── my-plugin.pot # Template file
|
|
223
|
+
│ ├── my-plugin-es_ES.po # Spanish translation
|
|
224
|
+
│ ├── my-plugin-es_ES.mo # Spanish compiled
|
|
225
|
+
│ ├── my-plugin-fr_FR.po # French translation
|
|
226
|
+
│ ├── my-plugin-fr_FR.mo # French compiled
|
|
227
|
+
│ └── my-plugin-en_US-*.json # JavaScript translations
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### POT File Format
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
# Copyright (C) 2024 My Plugin
|
|
234
|
+
# This file is distributed under the GPL-2.0+.
|
|
235
|
+
msgid ""
|
|
236
|
+
msgstr ""
|
|
237
|
+
"Project-Id-Version: My Plugin 1.0.0\n"
|
|
238
|
+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/my-plugin\n"
|
|
239
|
+
"POT-Creation-Date: 2024-01-01 00:00:00+00:00\n"
|
|
240
|
+
"MIME-Version: 1.0\n"
|
|
241
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
242
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
243
|
+
|
|
244
|
+
#: includes/class-admin.php:45
|
|
245
|
+
msgid "Settings"
|
|
246
|
+
msgstr ""
|
|
247
|
+
|
|
248
|
+
#: includes/class-admin.php:67
|
|
249
|
+
#. translators: %s: user name
|
|
250
|
+
msgid "Hello %s"
|
|
251
|
+
msgstr ""
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Best Practices
|
|
257
|
+
|
|
258
|
+
### String Guidelines
|
|
259
|
+
|
|
260
|
+
✅ **DO**:
|
|
261
|
+
- Use complete sentences
|
|
262
|
+
- Provide translator comments for variables
|
|
263
|
+
- Use context for ambiguous strings
|
|
264
|
+
- Keep strings simple and clear
|
|
265
|
+
- Use proper grammar and punctuation
|
|
266
|
+
|
|
267
|
+
❌ **DON'T**:
|
|
268
|
+
- Concatenate translatable strings
|
|
269
|
+
- Use variables in text domain
|
|
270
|
+
- Split sentences across multiple strings
|
|
271
|
+
- Use HTML in translatable strings (when possible)
|
|
272
|
+
- Hard-code text without translation functions
|
|
273
|
+
|
|
274
|
+
### Translator Comments
|
|
275
|
+
|
|
276
|
+
```php
|
|
277
|
+
<?php
|
|
278
|
+
/* translators: %s: user name */
|
|
279
|
+
__( 'Welcome back, %s!', 'my-plugin' );
|
|
280
|
+
|
|
281
|
+
/* translators: 1: number of posts, 2: category name */
|
|
282
|
+
__( 'Found %1$d posts in %2$s', 'my-plugin' );
|
|
283
|
+
|
|
284
|
+
/* translators: This appears in the admin settings page */
|
|
285
|
+
__( 'Enable feature', 'my-plugin' );
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### HTML in Translations
|
|
289
|
+
|
|
290
|
+
```php
|
|
291
|
+
<?php
|
|
292
|
+
// ✅ CORRECT: Keep HTML outside when possible
|
|
293
|
+
echo '<strong>' . esc_html__( 'Important', 'my-plugin' ) . '</strong>';
|
|
294
|
+
|
|
295
|
+
// ✅ ACCEPTABLE: When HTML is necessary for meaning
|
|
296
|
+
echo wp_kses_post( __( 'Click <a href="#">here</a> to continue', 'my-plugin' ) );
|
|
297
|
+
|
|
298
|
+
// ❌ WRONG: Unnecessary HTML in string
|
|
299
|
+
__( '<div class="notice">Notice text</div>', 'my-plugin' );
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Date and Number Formatting
|
|
303
|
+
|
|
304
|
+
```php
|
|
305
|
+
<?php
|
|
306
|
+
// Format dates for localization
|
|
307
|
+
echo date_i18n( get_option( 'date_format' ), $timestamp );
|
|
308
|
+
|
|
309
|
+
// Format numbers
|
|
310
|
+
echo number_format_i18n( $number );
|
|
311
|
+
|
|
312
|
+
// Format currency (use appropriate plugin/library)
|
|
313
|
+
echo wc_price( $amount ); // WooCommerce example
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Testing Translations
|
|
319
|
+
|
|
320
|
+
### Test with Different Locales
|
|
321
|
+
|
|
322
|
+
```php
|
|
323
|
+
<?php
|
|
324
|
+
// Temporarily switch locale for testing
|
|
325
|
+
function my_plugin_test_translation() {
|
|
326
|
+
switch_to_locale( 'es_ES' );
|
|
327
|
+
|
|
328
|
+
$text = __( 'Hello World', 'my-plugin' );
|
|
329
|
+
echo $text; // Should output Spanish translation
|
|
330
|
+
|
|
331
|
+
restore_current_locale();
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Validation Checklist
|
|
336
|
+
|
|
337
|
+
- [ ] All user-facing strings use translation functions
|
|
338
|
+
- [ ] Text domain is consistent throughout
|
|
339
|
+
- [ ] Translator comments provided for variables
|
|
340
|
+
- [ ] Plural forms implemented correctly
|
|
341
|
+
- [ ] Context used for ambiguous strings
|
|
342
|
+
- [ ] JavaScript translations configured
|
|
343
|
+
- [ ] POT file generated and up-to-date
|
|
344
|
+
- [ ] No concatenated translatable strings
|
|
345
|
+
- [ ] HTML kept outside translations when possible
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Common Mistakes
|
|
350
|
+
|
|
351
|
+
### Variable Text Domain
|
|
352
|
+
|
|
353
|
+
```php
|
|
354
|
+
<?php
|
|
355
|
+
// ❌ WRONG: Variable text domain
|
|
356
|
+
$text_domain = 'my-plugin';
|
|
357
|
+
__( 'Hello', $text_domain );
|
|
358
|
+
|
|
359
|
+
// ✅ CORRECT: Literal text domain
|
|
360
|
+
__( 'Hello', 'my-plugin' );
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### String Concatenation
|
|
364
|
+
|
|
365
|
+
```php
|
|
366
|
+
<?php
|
|
367
|
+
// ❌ WRONG: Concatenation
|
|
368
|
+
echo __( 'You have', 'my-plugin' ) . ' ' . $count . ' ' . __( 'items', 'my-plugin' );
|
|
369
|
+
|
|
370
|
+
// ✅ CORRECT: Single string with placeholder
|
|
371
|
+
echo sprintf( __( 'You have %d items', 'my-plugin' ), $count );
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Missing Context
|
|
375
|
+
|
|
376
|
+
```php
|
|
377
|
+
<?php
|
|
378
|
+
// ❌ WRONG: Ambiguous without context
|
|
379
|
+
__( 'Post', 'my-plugin' ); // Noun or verb?
|
|
380
|
+
|
|
381
|
+
// ✅ CORRECT: Clear with context
|
|
382
|
+
_x( 'Post', 'noun', 'my-plugin' );
|
|
383
|
+
_x( 'Post', 'verb', 'my-plugin' );
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## WordPress.org Translation
|
|
389
|
+
|
|
390
|
+
### Automatic Translation
|
|
391
|
+
|
|
392
|
+
WordPress.org provides automatic translation infrastructure:
|
|
393
|
+
|
|
394
|
+
1. Upload plugin to WordPress.org
|
|
395
|
+
2. Translators contribute via translate.wordpress.org
|
|
396
|
+
3. Language packs automatically distributed
|
|
397
|
+
4. Users receive translations via WordPress updates
|
|
398
|
+
|
|
399
|
+
### Requirements
|
|
400
|
+
|
|
401
|
+
- POT file in `languages/` directory
|
|
402
|
+
- Proper text domain in plugin header
|
|
403
|
+
- All strings properly internationalized
|
|
404
|
+
- Text domain matches plugin slug
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Resources
|
|
409
|
+
|
|
410
|
+
- [WordPress I18n Documentation](https://developer.wordpress.org/plugins/internationalization/)
|
|
411
|
+
- [WP-CLI i18n Commands](https://developer.wordpress.org/cli/commands/i18n/)
|
|
412
|
+
- [GlotPress](https://wordpress.org/plugins/glotpress/)
|
|
413
|
+
- [Poedit](https://poedit.net/)
|
|
414
|
+
- [translate.wordpress.org](https://translate.wordpress.org/)
|
|
415
|
+
|
|
416
|
+
|