searchStringInProject
Find translations containing specific text in a Weblate project by searching source strings, target translations, or both.
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 | |
| value | Yes | The text to search for | |
| searchIn | No | Where to search: source text, target translation, or both | both |
Implementation Reference
- src/tools/translations.tool.ts:13-86 (handler)The primary MCP tool handler for 'searchStringInProject'. Includes @Tool decorator with Zod schema for input validation, business logic for calling the service, result formatting (limiting to 10, using formatTranslationResult helper), error handling, and response structuring for MCP.@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/tools/translations.tool.ts:17-25 (schema)Zod schema definition for the tool parameters within the @Tool decorator.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'), }),
- src/app.module.ts:65-80 (registration)Registration of WeblateTranslationsTool in the NestJS AppModule providers array, which enables MCP to discover and register the @Tool decorated methods.providers: [ WeblateClientService, WeblateProjectsService, WeblateComponentsService, WeblateLanguagesService, WeblateTranslationsService, WeblateChangesService, WeblateApiService, WeblateStatisticsService, WeblateProjectsTool, WeblateComponentsTool, WeblateLanguagesTool, WeblateTranslationsTool, WeblateChangesTool, WeblateStatisticsTool, ],
- Facade helper method in WeblateApiService that proxies the searchStringInProject call to the underlying translations service.async searchStringInProject( projectSlug: string, searchValue: string, searchIn: SearchIn = 'both', ): Promise<Unit[]> { return this.translationsService.searchStringInProject( projectSlug, searchValue, searchIn, ); }
- Core implementation helper that performs the actual Weblate API search for strings in source and/or target across the project, combines results, deduplicates by unit ID, using the internal searchTranslations method.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}`, ); } }