feat(keywords): rename brand-question terminology to search-keyword + add entity exclusion
- Rename UI/prompt labels: "品牌主问题" → "优化关键词", "搜索问题" → "搜索词" - Add brand/competitor entity exclusion filter in question expansion (AI distill path) - Refactor combination question text normalization, remove manual question-mark appending - Update prompts to emphasize commercial-intent search queries over editorial phrasing - Sync prompt changes across server/configs, deploy, and k3s configs - Update i18n, frontend views (BrandQuestionCreate, TemplateWizard), and test fixtures Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -154,7 +154,7 @@ const enUS = {
|
||||
template_outline_generate: 'AI Outline Generation',
|
||||
kol_prompt_generate: 'KOL Prompt Generation',
|
||||
kol_prompt_optimize: 'KOL Prompt Optimize',
|
||||
question_distill: 'AI Candidate Question Generation',
|
||||
question_distill: 'AI Candidate Search Term Generation',
|
||||
question_combination_fill: 'Expansion Tool AI Fill',
|
||||
},
|
||||
aiUsageStatus: {
|
||||
@@ -214,12 +214,13 @@ const enUS = {
|
||||
'Review desktop publish tasks, external links, account workbench entry points, and retry state.',
|
||||
},
|
||||
brands: {
|
||||
title: 'Brand Library',
|
||||
description: 'Manage keywords, question sets, and competitors around each brand.',
|
||||
title: 'Company & Lexicon',
|
||||
description: 'Manage the keyword library (search terms) and competitors around each brand.',
|
||||
},
|
||||
brandQuestionCreate: {
|
||||
title: 'New question',
|
||||
description: 'Create brand questions with the expansion tool, AI expansion, or manual input.',
|
||||
title: 'New search term',
|
||||
description:
|
||||
'Create brand search terms with the expansion tool, AI expansion, or manual input.',
|
||||
},
|
||||
tracking: {
|
||||
title: 'Data Details',
|
||||
@@ -459,11 +460,11 @@ const enUS = {
|
||||
},
|
||||
tracking: {
|
||||
brandPlaceholder: 'Select brand',
|
||||
keywordPlaceholder: 'Select question set',
|
||||
allQuestionSets: 'All question sets',
|
||||
keywordPlaceholder: 'Select keyword library (search terms)',
|
||||
allQuestionSets: 'All keyword library (search terms)',
|
||||
collectNow: 'Collect Now',
|
||||
collectBrandRequired: 'Select a brand before collecting.',
|
||||
collectKeywordRequired: 'Select a question set before collecting.',
|
||||
collectKeywordRequired: 'Select a keyword library (search terms) before collecting.',
|
||||
collectTodayOnly: "Collect Now only supports today's data. Switch back to today to continue.",
|
||||
collectClientChecking: "Checking whether the current account's desktop client is online.",
|
||||
collectClientOnlineRequired:
|
||||
@@ -488,7 +489,7 @@ const enUS = {
|
||||
hotQuestions: 'Hot Questions',
|
||||
hotQuestionsTitle: 'Hot Questions',
|
||||
hotQuestionsHint:
|
||||
'Choose all question sets or one specific question. Selecting one question limits display and collection to that question.',
|
||||
'Choose the full keyword library (search terms) or one specific search term. Selecting one search term limits display and collection to that term.',
|
||||
questionSearchPlaceholder: 'Search questions in the selected scope',
|
||||
questionDetailEyebrow: 'Question Detail',
|
||||
questionDetailCollectedAt: 'Collected at {time}',
|
||||
@@ -841,13 +842,13 @@ const enUS = {
|
||||
language: 'Language',
|
||||
brandInfo: 'Brand',
|
||||
brandLibrary: 'Brand library',
|
||||
brandName: 'Brand name',
|
||||
brandName: 'Company name',
|
||||
website: 'Official website',
|
||||
brandSummary: 'AI brand summary',
|
||||
keywords: 'Keywords',
|
||||
brandQuestions: 'Brand questions',
|
||||
primaryQuestion: 'Primary brand question',
|
||||
supplementalQuestions: 'Supplemental questions',
|
||||
brandQuestions: 'Keyword library (search terms)',
|
||||
primaryQuestion: 'Optimization keyword',
|
||||
supplementalQuestions: 'Supplemental keywords',
|
||||
competitors: 'Competitors',
|
||||
chooseTitle: 'Choose a title',
|
||||
customTitle: 'Custom title',
|
||||
@@ -864,17 +865,17 @@ const enUS = {
|
||||
hints: {
|
||||
brandContext: 'Optional. Selecting a brand pulls in keywords and competitor context.',
|
||||
brandFlow:
|
||||
'You can pick a brand from the library or type one manually. After you choose a brand question, AI will prepare the summary, competitors, and title options.',
|
||||
'You can type a company name or choose one from the brand library. After you choose an optimization keyword, AI will prepare the summary, competitors, and title options.',
|
||||
brandSummaryPlaceholder:
|
||||
'After analysis, AI will summarize the brand angle, positioning, and content opportunities here.',
|
||||
keywords:
|
||||
'Type keywords directly or reuse brand-library keywords. AI results will be merged into this list.',
|
||||
brandQuestions:
|
||||
'The primary question controls the article spine; supplemental questions broaden nearby search intent.',
|
||||
'The optimization keyword controls the article spine; supplemental keywords broaden nearby search intent.',
|
||||
supplementalQuestions:
|
||||
'Choose up to 3 so the article covers related intent without drifting.',
|
||||
questionEmpty: 'No questions are available for this brand yet.',
|
||||
selectBrandFirst: 'Choose a brand from the library first.',
|
||||
selectBrandFirst: 'Choose a library brand from the company name dropdown first.',
|
||||
competitors:
|
||||
'Competitors stay editable. You can add rows manually; saving to the competitor library is only available after choosing a library brand.',
|
||||
competitorEmptyEditable:
|
||||
@@ -931,11 +932,11 @@ const enUS = {
|
||||
},
|
||||
placeholders: {
|
||||
brandLibrary: 'Choose an existing brand from the library',
|
||||
brandName: 'Enter a brand name, or refine the selected library brand',
|
||||
brandName: 'Enter a company name, or choose from the brand library',
|
||||
website: 'Official website, optional',
|
||||
keywords: 'Type keywords and press Enter',
|
||||
primaryQuestion: 'Choose one primary brand question',
|
||||
supplementalQuestions: 'Optional, choose up to 3 supplemental questions',
|
||||
primaryQuestion: 'Choose one optimization keyword',
|
||||
supplementalQuestions: 'Optional, choose up to 3 supplemental keywords',
|
||||
customTitle: 'Override the AI title here if needed',
|
||||
customOutline: 'Add another section, for example “Buying advice”',
|
||||
keyPoints: 'Add any extra instructions, key angles, or constraints for the article',
|
||||
@@ -949,9 +950,9 @@ const enUS = {
|
||||
aiBanner: {
|
||||
title: 'One-click AI analysis',
|
||||
defaultDescription:
|
||||
'AI will use the brand question to complete the brand summary and extract competitor context.',
|
||||
'AI will use the optimization keyword to complete the brand summary and extract competitor context.',
|
||||
productReviewDescription:
|
||||
'AI will use the brand question to organize the product context and suggest comparable alternatives.',
|
||||
'AI will use the optimization keyword to organize the product context and suggest comparable alternatives.',
|
||||
researchReportDescription:
|
||||
'AI will use the brand question to organize the topic context and suggest reference targets.',
|
||||
},
|
||||
@@ -983,15 +984,18 @@ const enUS = {
|
||||
},
|
||||
messages: {
|
||||
requiredField: 'Please fill in {field} first.',
|
||||
missingBrand: 'Choose a brand from the library or enter a brand name first.',
|
||||
selectBrandBeforeQuestion: 'Choose a brand from the library before selecting a question.',
|
||||
missingBrand: 'Enter or choose a company name first.',
|
||||
selectBrandBeforeQuestion:
|
||||
'Choose a library brand from the company name dropdown before selecting a question.',
|
||||
missingPrimaryQuestion: 'Choose one primary brand question.',
|
||||
missingTitle: 'Please choose or enter an article title.',
|
||||
missingOutline: 'Please select at least one outline section.',
|
||||
missingGeneratedOutline: 'Please generate and confirm the article outline first.',
|
||||
customOutlineTooLong: 'Custom sections cannot exceed {count} characters.',
|
||||
selectBrandBeforeCompetitors: 'Choose a brand from the library before managing competitors.',
|
||||
selectBrandBeforeFavorite: 'Choose a brand from the library before saving competitors.',
|
||||
selectBrandBeforeCompetitors:
|
||||
'Choose a library brand from the company name dropdown before managing competitors.',
|
||||
selectBrandBeforeFavorite:
|
||||
'Choose a library brand from the company name dropdown before saving competitors.',
|
||||
missingCompetitorName: 'Enter a competitor name before saving it to the library.',
|
||||
savedCompetitor: 'Competitor saved to the brand library.',
|
||||
unsavedCompetitor: 'Competitor removed from the brand library.',
|
||||
@@ -1285,20 +1289,21 @@ const enUS = {
|
||||
},
|
||||
},
|
||||
brands: {
|
||||
eyebrow: 'Brand Library',
|
||||
title: 'Brand Management',
|
||||
description: 'Manage question sets and competitor assets around each brand.',
|
||||
eyebrow: 'Company & Lexicon',
|
||||
title: 'Company & Lexicon',
|
||||
description: 'Manage the keyword library (search terms) and competitor assets around each brand.',
|
||||
railTitle: 'Brands',
|
||||
selectBrand: 'Pick a brand to continue managing question sets.',
|
||||
selectBrand: 'Pick a brand to continue managing the keyword library (search terms).',
|
||||
newBrand: 'New brand',
|
||||
editBrand: 'Edit brand',
|
||||
deleteBrand: 'Delete brand',
|
||||
guide: {
|
||||
title: 'Brand management guide',
|
||||
body: 'Manage brands, question sets, and competitor libraries for AI platform monitoring and GEO analysis.',
|
||||
body:
|
||||
'Manage brands, the keyword library (search terms), and competitor libraries for AI platform monitoring and GEO analysis.',
|
||||
},
|
||||
tabs: {
|
||||
questions: 'Question set',
|
||||
questions: 'Keyword library (search terms)',
|
||||
competitors: 'Competitors',
|
||||
},
|
||||
quota: {
|
||||
@@ -1321,20 +1326,20 @@ const enUS = {
|
||||
},
|
||||
sections: {
|
||||
keywords: 'Keywords',
|
||||
questions: 'Question set',
|
||||
questions: 'Keyword library (search terms)',
|
||||
competitors: 'Competitor library',
|
||||
versions: 'Version history',
|
||||
},
|
||||
actions: {
|
||||
addBrand: 'Add brand',
|
||||
newKeyword: 'New keyword',
|
||||
newQuestion: 'New question',
|
||||
newQuestion: 'New search term',
|
||||
newCompetitor: 'New competitor',
|
||||
viewVersions: 'View versions',
|
||||
},
|
||||
empty: {
|
||||
brands: 'No brand data yet. Create your first brand to start.',
|
||||
questions: 'No questions under this brand yet.',
|
||||
questions: 'No search terms under this brand yet.',
|
||||
competitors: 'No competitors under this brand yet.',
|
||||
brandDescription: 'No brand description yet',
|
||||
competitorDescription: 'No competitor description yet',
|
||||
@@ -1344,7 +1349,7 @@ const enUS = {
|
||||
brandWebsite: 'Company website (optional)',
|
||||
brandDescription: 'Brand description',
|
||||
keywordName: 'Keyword',
|
||||
questionText: 'Question text',
|
||||
questionText: 'Search term',
|
||||
competitorName: 'Competitor name',
|
||||
competitorWebsite: 'Competitor website',
|
||||
competitorDescription: 'Competitor description',
|
||||
@@ -1358,9 +1363,9 @@ const enUS = {
|
||||
createKeyword: 'Keyword created.',
|
||||
updateKeyword: 'Keyword updated.',
|
||||
deleteKeyword: 'Keyword deleted.',
|
||||
createQuestion: 'Question created.',
|
||||
updateQuestion: 'Question updated.',
|
||||
deleteQuestion: 'Question deleted.',
|
||||
createQuestion: 'Search term created.',
|
||||
updateQuestion: 'Search term updated.',
|
||||
deleteQuestion: 'Search term deleted.',
|
||||
createCompetitor: 'Competitor created.',
|
||||
updateCompetitor: 'Competitor updated.',
|
||||
deleteCompetitor: 'Competitor deleted.',
|
||||
@@ -1368,21 +1373,21 @@ const enUS = {
|
||||
chooseKeyword: 'Please choose a keyword first.',
|
||||
brandLimitReached: 'Your current plan allows up to {limit} brand companies.',
|
||||
keywordLimitReached: 'This account allows up to {limit} keywords.',
|
||||
questionLimitReached: 'This account allows up to {limit} questions.',
|
||||
questionLimitReached: 'This account allows up to {limit} search terms.',
|
||||
},
|
||||
questions: {
|
||||
create: 'New question',
|
||||
createSingle: 'Add single question',
|
||||
expand: 'Bulk expand questions',
|
||||
usage: 'Questions {used} / {total}',
|
||||
create: 'New search term',
|
||||
createSingle: 'Add single search term',
|
||||
expand: 'Bulk expand search terms',
|
||||
usage: 'Search terms {used} / {total}',
|
||||
remaining: '{count} remaining',
|
||||
generate: 'Generate candidates',
|
||||
emptyCandidates: 'No candidates yet. Generate or paste questions above.',
|
||||
emptyCandidates: 'No candidates yet. Generate or paste search terms above.',
|
||||
table: {
|
||||
question: 'Question set',
|
||||
question: 'Keyword library (search terms)',
|
||||
},
|
||||
modal: {
|
||||
title: 'New question',
|
||||
title: 'New search term',
|
||||
currentBrand: 'Current brand',
|
||||
methods: {
|
||||
single: 'Single',
|
||||
@@ -1393,17 +1398,17 @@ const enUS = {
|
||||
preview: 'Candidate preview',
|
||||
summary:
|
||||
'{total} candidates · {selected} selected · {tooShort} too short · {duplicate} duplicates',
|
||||
save: 'Save questions ({count})',
|
||||
save: 'Save search terms ({count})',
|
||||
},
|
||||
combination: {
|
||||
region: '1. Region',
|
||||
prefix: '2. Prefix',
|
||||
core: '3. Core (required)',
|
||||
core: '3. Precise term (required)',
|
||||
industry: '4. Industry (required)',
|
||||
suffix: '5. Suffix',
|
||||
defaultWord: 'Default',
|
||||
estimate: '{count} candidates estimated',
|
||||
coreRequired: 'Core is required',
|
||||
coreRequired: 'Precise term is required',
|
||||
industryRequired: 'Industry is required',
|
||||
},
|
||||
aiFill: {
|
||||
@@ -1414,25 +1419,25 @@ const enUS = {
|
||||
waitingStages: {
|
||||
region: 'Detecting city, province capital, and macro region...',
|
||||
generate: 'Analyzing brand context and high-frequency intent...',
|
||||
refine: 'Refining short combinable keyword groups...',
|
||||
refine: 'Refining short combinable precise term groups...',
|
||||
},
|
||||
},
|
||||
ai: {
|
||||
note: 'AI expansion consumes 1 AI point. Failed generations are refunded automatically.',
|
||||
seedTopic: 'Seed topic',
|
||||
seedTopicPlaceholder: 'Enter a topic and press Enter; multiple topics supported',
|
||||
seedTopic: 'User search term',
|
||||
seedTopicPlaceholder: 'Enter a search term and press Enter; multiple terms supported',
|
||||
seedTopicHint:
|
||||
'Use Enter, commas, or semicolons to add multiple topics. Candidates are merged and deduplicated automatically.',
|
||||
'Candidates expand from user search terms with strong commercial intent. The company name is a target term, not a candidate search term.',
|
||||
generate: 'Generate with AI',
|
||||
waitingTitle: 'AI is generating candidate questions. Please wait...',
|
||||
waitingTitle: 'AI is generating candidate search terms. Please wait...',
|
||||
waitingStages: {
|
||||
context: 'Organizing brand and topic context...',
|
||||
generate: 'Generating high-intent candidate questions...',
|
||||
refine: 'Deduplicating and filtering savable questions...',
|
||||
context: 'Organizing user search terms and the target term...',
|
||||
generate: 'Generating commercial candidate search terms suited for recommending companies...',
|
||||
refine: 'Deduplicating and filtering savable search terms...',
|
||||
},
|
||||
},
|
||||
batch: {
|
||||
label: 'One question per line',
|
||||
label: 'One search term per line',
|
||||
},
|
||||
badges: {
|
||||
duplicate: 'Duplicate',
|
||||
@@ -1440,20 +1445,22 @@ const enUS = {
|
||||
},
|
||||
messages: {
|
||||
partialSaved: 'Saved {created}; skipped {skipped}.',
|
||||
limitReached: 'This account allows up to {limit} questions shared across all brands.',
|
||||
selectionLimitReached: 'This plan allows up to {limit} questions. Selection limit reached.',
|
||||
limitReached: 'This account allows up to {limit} search terms shared across all brands.',
|
||||
selectionLimitReached:
|
||||
'This plan allows up to {limit} search terms. Selection limit reached.',
|
||||
truncated: 'Candidates exceeded the limit and were truncated to 500.',
|
||||
cacheHit: 'Used the most recent AI expansion result.',
|
||||
aiCharged: 'This AI expansion consumed {count} AI point.',
|
||||
},
|
||||
errors: {
|
||||
emptyInput: 'Enter question content first.',
|
||||
emptyInput: 'Enter search term content first.',
|
||||
noSelection: 'Select at least one candidate.',
|
||||
noValidQuestions: 'No valid questions can be saved. Adjust candidates and try again.',
|
||||
noValidQuestions: 'No valid search terms can be saved. Adjust candidates and try again.',
|
||||
},
|
||||
page: {
|
||||
title: 'New question',
|
||||
subtitle: 'Generate candidates, review them, then save them to this brand question set.',
|
||||
title: 'New search term',
|
||||
subtitle:
|
||||
'Generate candidates, review them, then save them to this brand keyword library (search terms).',
|
||||
steps: {
|
||||
configure: 'Configure',
|
||||
preview: 'Review candidates',
|
||||
@@ -1462,13 +1469,13 @@ const enUS = {
|
||||
methodHint:
|
||||
'Candidates remain temporary until saved, so you can generate, edit, and select first.',
|
||||
methods: {
|
||||
combination: 'Expand candidates from the column-based word tool.',
|
||||
ai: 'Let AI generate candidates around a seed topic.',
|
||||
batch: 'Paste questions from a sheet or document.',
|
||||
combination: 'Expand search term candidates from the column-based word tool.',
|
||||
ai: 'Let AI generate search term candidates around a seed topic.',
|
||||
batch: 'Paste search terms from a sheet or document.',
|
||||
},
|
||||
expansionHint:
|
||||
'One word per line. Empty optional columns are skipped; core and industry are required.',
|
||||
batchHint: 'One question per line. You can edit and select each one before saving.',
|
||||
'One word per line. Empty optional columns are skipped; precise term and industry are required.',
|
||||
batchHint: 'One search term per line. You can edit and select each one before saving.',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user