searchStringInProject
Locate specific text within translation projects by searching source, target, or both in Weblate MCP Server.
Instructions
Search for translations containing specific text in a project
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectSlug | Yes | The slug of the project to search in | |
| searchIn | No | Where to search: source text, target translation, or both | both |
| value | Yes | The text to search for |
Implementation Reference
- src/tools/translations.tool.ts:13-86 (handler)Primary tool handler: @Tool decorator with name, description, Zod schema; executes search via service, limits to 10 results, formats output, handles empty results and errors.@Tool({ name: 'searchStringInProject', description: 'Search for translations containing specific text in a project', parameters: z.object({ projectSlug: z.string().describe('The slug of the project to search in'), value: z.string().describe('The text to search for'), searchIn: z .enum(['source', 'target', 'both']) .optional() .describe('Where to search: source text, target translation, or both') .default('both'), }), }) async searchStringInProject({ projectSlug, value, searchIn = 'both', }: { projectSlug: string; value: string; searchIn?: 'source' | 'target' | 'both'; }) { try { const results = await this.weblateApiService.searchStringInProject( projectSlug, value, searchIn, ); if (results.length === 0) { return { content: [ { type: 'text', text: `No translations found containing "${value}" in project "${projectSlug}"`, }, ], }; } const formattedResults = results .slice(0, 10) .map(this.formatTranslationResult) .join('\n\n'); const totalText = results.length > 10 ? `\n\n*Showing first 10 of ${results.length} results*` : ''; return { content: [ { type: 'text', text: `Found ${results.length} translations containing "${value}" in project "${projectSlug}":\n\n${formattedResults}${totalText}`, }, ], }; } catch (error) { this.logger.error( `Failed to search for "${value}" in ${projectSlug}`, error, ); return { content: [ { type: 'text', text: `Error searching for "${value}" in project "${projectSlug}": ${error.message}`, }, ], isError: true, }; } }
- src/app.module.ts:66-81 (registration)MCP tool registration: WeblateTranslationsTool class (containing searchStringInProject handler) is provided in AppModule, making it available to McpModule for tool discovery.WeblateClientService, WeblateProjectsService, WeblateComponentsService, WeblateLanguagesService, WeblateTranslationsService, WeblateChangesService, WeblateApiService, WeblateStatisticsService, WeblateProjectsTool, WeblateComponentsTool, WeblateLanguagesTool, WeblateTranslationsTool, WeblateChangesTool, WeblateStatisticsTool, ], })
- src/tools/translations.tool.ts:17-25 (schema)Zod input schema defining parameters for the tool: projectSlug (string), value (string), searchIn (enum: source|target|both, default 'both').parameters: z.object({ projectSlug: z.string().describe('The slug of the project to search in'), value: z.string().describe('The text to search for'), searchIn: z .enum(['source', 'target', 'both']) .optional() .describe('Where to search: source text, target translation, or both') .default('both'), }),
- Private helper method to format individual translation results for output, used in handler to create readable summaries.private formatTranslationResult(translation: Unit): string { const status = translation.approved ? '✅ Approved' : translation.translated ? '📝 Translated' : '❌ Untranslated'; const sourceText = translation.source && Array.isArray(translation.source) ? translation.source.join('') : (translation.source || '(empty)'); const targetText = translation.target && Array.isArray(translation.target) ? translation.target.join('') : (translation.target || '(empty)'); return `**Key:** ${translation.context} **Source:** ${sourceText} **Target:** ${targetText} **Status:** ${status} **Context:** ${translation.context || '(none)'} **Note:** ${translation.note || '(none)'} **ID:** ${translation.id}`; }
- Core search logic: searches source and/or target texts across project using Weblate API, deduplicates results by unit ID.async searchStringInProject( projectSlug: string, searchValue: string, searchIn: SearchIn = 'both', ): Promise<Unit[]> { try { let results: Unit[] = []; if (searchIn === 'source' || searchIn === 'both') { const sourceResults = await this.searchTranslations( projectSlug, undefined, undefined, undefined, searchValue, ); results = results.concat(sourceResults.results); } if (searchIn === 'target' || searchIn === 'both') { const targetResults = await this.searchTranslations( projectSlug, undefined, undefined, undefined, undefined, searchValue, ); results = results.concat(targetResults.results); } // Remove duplicates based on unit ID const uniqueResults = results.filter( (unit, index, self) => index === self.findIndex(u => u.id === unit.id) ); return uniqueResults; } catch (error) { this.logger.error( `Failed to search string in project ${projectSlug}`, error, ); throw new Error( `Failed to search string in project: ${error.message}`, ); } }