feat(i18n): enhance caching and data fetching for language support

- Update Content and ProductFilters components to include language in cache keys for category and product data.
- Modify componentDidUpdate to handle language changes, ensuring data is re-fetched or filtered appropriately.
- Improve state management by tracking the last fetched language, enhancing internationalization support across the application.
This commit is contained in:
sebseb7
2025-11-12 07:26:35 +01:00
parent e00c226b9a
commit 4ae9344b63
2 changed files with 86 additions and 39 deletions

View File

@@ -27,13 +27,13 @@ const withRouter = (ClassComponent) => {
};
};
function getCachedCategoryData(categoryId) {
function getCachedCategoryData(categoryId, language = 'de') {
if (!window.productCache) {
window.productCache = {};
}
try {
const cacheKey = `categoryProducts_${categoryId}`;
const cacheKey = `categoryProducts_${categoryId}_${language}`;
const cachedData = window.productCache[cacheKey];
if (cachedData) {
@@ -165,7 +165,7 @@ function getFilteredProducts(unfilteredProducts, attributes, t) {
return {filteredProducts,activeAttributeFilters:activeAttributeFiltersWithNames,activeManufacturerFilters:activeManufacturerFiltersWithNames,activeAvailabilityFilters};
}
function setCachedCategoryData(categoryId, data) {
function setCachedCategoryData(categoryId, data, language = 'de') {
if (!window.productCache) {
window.productCache = {};
}
@@ -174,7 +174,7 @@ function setCachedCategoryData(categoryId, data) {
}
try {
const cacheKey = `categoryProducts_${categoryId}`;
const cacheKey = `categoryProducts_${categoryId}_${language}`;
if(data.products) for(const product of data.products) {
window.productDetailCache[product.id] = product;
}
@@ -197,40 +197,77 @@ class Content extends Component {
unfilteredProducts: [],
filteredProducts: [],
attributes: [],
childCategories: []
childCategories: [],
lastFetchedLanguage: props.i18n?.language || 'de'
};
}
componentDidMount() {
if(this.props.params.categoryId) {this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: []}, () => {
const currentLanguage = this.props.i18n?.language || 'de';
if(this.props.params.categoryId) {this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: [], lastFetchedLanguage: currentLanguage}, () => {
this.fetchCategoryData(this.props.params.categoryId);
})}
else if (this.props.searchParams?.get('q')) {
this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: []}, () => {
this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: [], lastFetchedLanguage: currentLanguage}, () => {
this.fetchSearchData(this.props.searchParams?.get('q'));
})
}
}
componentDidUpdate(prevProps) {
if(this.props.params.categoryId && (prevProps.params.categoryId !== this.props.params.categoryId)) {
const currentLanguage = this.props.i18n?.language || 'de';
const categoryChanged = this.props.params.categoryId && (prevProps.params.categoryId !== this.props.params.categoryId);
const searchChanged = this.props.searchParams?.get('q') && (prevProps.searchParams?.get('q') !== this.props.searchParams?.get('q'));
if(categoryChanged) {
window.currentSearchQuery = null;
this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: []}, () => {
this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: [], lastFetchedLanguage: currentLanguage}, () => {
this.fetchCategoryData(this.props.params.categoryId);
});
});
return; // Don't check language change if category changed
}
else if (this.props.searchParams?.get('q') && (prevProps.searchParams?.get('q') !== this.props.searchParams?.get('q'))) {
this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: []}, () => {
else if (searchChanged) {
this.setState({loaded: false, unfilteredProducts: [], filteredProducts: [], attributes: [], categoryName: null, childCategories: [], lastFetchedLanguage: currentLanguage}, () => {
this.fetchSearchData(this.props.searchParams?.get('q'));
})
});
return; // Don't check language change if search changed
}
// Re-filter products when language changes to update translated filter names
const languageChanged = this.props.i18n && prevProps.i18n && this.props.i18n.language !== prevProps.i18n.language;
const tFunctionChanged = this.props.t !== prevProps.t;
// Re-fetch products when language changes to get translated content
const languageChanged = currentLanguage !== this.state.lastFetchedLanguage;
if(languageChanged || tFunctionChanged) {
this.filterProducts();
console.log('Content componentDidUpdate:', {
languageChanged,
lastFetchedLang: this.state.lastFetchedLanguage,
currentLang: currentLanguage,
prevPropsLang: prevProps.i18n?.language,
hasCategoryId: !!this.props.params.categoryId,
categoryId: this.props.params.categoryId,
hasSearchQuery: !!this.props.searchParams?.get('q')
});
if(languageChanged) {
console.log('Content: Language changed! Re-fetching data...');
// Re-fetch current data with new language
// Note: Language is now part of the cache key, so it will automatically fetch fresh data
if(this.props.params.categoryId) {
// Re-fetch category data with new language
console.log('Content: Re-fetching category', this.props.params.categoryId);
this.setState({loaded: false, lastFetchedLanguage: currentLanguage}, () => {
this.fetchCategoryData(this.props.params.categoryId);
});
} else if(this.props.searchParams?.get('q')) {
// Re-fetch search data with new language
console.log('Content: Re-fetching search', this.props.searchParams?.get('q'));
this.setState({loaded: false, lastFetchedLanguage: currentLanguage}, () => {
this.fetchSearchData(this.props.searchParams?.get('q'));
});
} else {
// If not viewing category or search, just re-filter existing products
console.log('Content: Just re-filtering existing products');
this.setState({lastFetchedLanguage: currentLanguage});
this.filterProducts();
}
}
}
@@ -267,7 +304,8 @@ class Content extends Component {
fetchCategoryData(categoryId) {
const cachedData = getCachedCategoryData(categoryId);
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n?.language || 'de';
const cachedData = getCachedCategoryData(categoryId, currentLanguage);
if (cachedData) {
this.processDataWithCategoryTree(cachedData, categoryId);
return;
@@ -282,7 +320,7 @@ class Content extends Component {
window.socketManager.on(`productList:${categoryId}`,(response) => {
console.log("getCategoryProducts full response", response);
receivedFullResponse = true;
setCachedCategoryData(categoryId, response);
setCachedCategoryData(categoryId, response, currentLanguage);
if (response && response.products !== undefined) {
this.processDataWithCategoryTree(response, categoryId);
} else {
@@ -290,7 +328,6 @@ class Content extends Component {
}
});
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n?.language || 'de';
window.socketManager.emit(
"getCategoryProducts",
{ categoryId: categoryId, language: currentLanguage, requestTranslation: currentLanguage === 'de' ? false : true },
@@ -298,7 +335,7 @@ class Content extends Component {
console.log("getCategoryProducts stub response", response);
// Only process stub response if we haven't received the full response yet
if (!receivedFullResponse) {
setCachedCategoryData(categoryId, response);
setCachedCategoryData(categoryId, response, currentLanguage);
if (response && response.products !== undefined) {
this.processDataWithCategoryTree(response, categoryId);
} else {

View File

@@ -48,14 +48,37 @@ class ProductFilters extends Component {
}
componentDidUpdate(prevProps) {
// Regenerate availability values when language changes
// Check both i18n.language and the t function itself
// Regenerate values when products, attributes, or language changes
const productsChanged = this.props.products !== prevProps.products;
const attributesChanged = this.props.attributes !== prevProps.attributes;
const languageChanged = this.props.i18n && prevProps.i18n && this.props.i18n.language !== prevProps.i18n.language;
const tFunctionChanged = this.props.t !== prevProps.t;
if(languageChanged || tFunctionChanged) {
if(languageChanged) {
console.log('ProductFilters: Language changed, will update when new data arrives');
}
if(productsChanged || languageChanged || tFunctionChanged) {
console.log('ProductFilters: Updating manufacturers and availability', {
productsChanged,
languageChanged,
tFunctionChanged,
productCount: this.props.products?.length
});
const uniqueManufacturerArray = this._getUniqueManufacturers(this.props.products);
const availabilityValues = this._getAvailabilityValues(this.props.products);
this.setState({availabilityValues});
this.setState({uniqueManufacturerArray, availabilityValues});
}
if(attributesChanged || (languageChanged && this.props.attributes)) {
console.log('ProductFilters: Updating attributes', {
attributesChanged,
languageChanged,
attributeCount: this.props.attributes?.length,
firstAttribute: this.props.attributes?.[0]
});
const attributeGroups = this._getAttributeGroups(this.props.attributes);
this.setState({attributeGroups});
}
}
@@ -128,19 +151,6 @@ class ProductFilters extends Component {
return attributeGroups;
}
shouldComponentUpdate(nextProps) {
if(nextProps.products !== this.props.products) {
const uniqueManufacturerArray = this._getUniqueManufacturers(nextProps.products);
const availabilityValues = this._getAvailabilityValues(nextProps.products);
this.setState({uniqueManufacturerArray, availabilityValues});
}
if(nextProps.attributes !== this.props.attributes) {
const attributeGroups = this._getAttributeGroups(nextProps.attributes);
this.setState({attributeGroups});
}
return true;
}
generateAttributeFilters = () => {
const filters = [];
const sortedAttributeGroups = Object.values(this.state.attributeGroups)