Compare commits

...

4 Commits

Author SHA1 Message Date
Matt Fiddaman
05e2cbede1 bump versions to v25.2.1 2025-02-06 18:21:40 +00:00
Michael Clark
fd42689f00 Fix electron translations (#4317)
* fix electron translations
2025-02-06 18:20:19 +00:00
Matt Fiddaman
dd58376aa9 fix Weblate URL if language has never been changed (#4312)
* fix weblate URL if language has never been changed

* note
2025-02-06 18:20:14 +00:00
Julian Dominguez-Schatz
3c1f98daf1 Fix crashes on reports page with translations enabled (#4303)
* Fix crashes

* Add release notes
2025-02-06 18:20:05 +00:00
13 changed files with 98 additions and 41 deletions

View File

@@ -36,6 +36,16 @@ fi
yarn workspace loot-core build:node yarn workspace loot-core build:node
# Get translations
echo "Updating translations..."
if ! [ -d packages/desktop-client/locale ]; then
git clone https://github.com/actualbudget/translations packages/desktop-client/locale
fi
pushd packages/desktop-client/locale > /dev/null
git pull
popd > /dev/null
packages/desktop-client/bin/remove-untranslated-languages
yarn workspace @actual-app/web build --mode=desktop # electron specific build yarn workspace @actual-app/web build --mode=desktop # electron specific build
yarn workspace desktop-electron update-client yarn workspace desktop-electron update-client

View File

@@ -1,6 +1,6 @@
{ {
"name": "@actual-app/api", "name": "@actual-app/api",
"version": "25.2.0", "version": "25.2.1",
"license": "MIT", "license": "MIT",
"description": "An API for Actual", "description": "An API for Actual",
"engines": { "engines": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@actual-app/web", "name": "@actual-app/web",
"version": "25.2.0", "version": "25.2.1",
"license": "MIT", "license": "MIT",
"files": [ "files": [
"build" "build"

View File

@@ -36,33 +36,43 @@ export const defaultReport: CustomReportEntity = {
}; };
const balanceTypeOptions = [ const balanceTypeOptions = [
{ description: t('Payment'), format: 'totalDebts' as const }, { description: t('Payment'), key: 'Payment', format: 'totalDebts' as const },
{ description: t('Deposit'), format: 'totalAssets' as const }, { description: t('Deposit'), key: 'Deposit', format: 'totalAssets' as const },
{ description: t('Net'), format: 'totalTotals' as const }, { description: t('Net'), key: 'Net', format: 'totalTotals' as const },
{ description: t('Net Payment'), format: 'netDebts' as const }, {
{ description: t('Net Deposit'), format: 'netAssets' as const }, description: t('Net Payment'),
key: 'Net Payment',
format: 'netDebts' as const,
},
{
description: t('Net Deposit'),
key: 'Net Deposit',
format: 'netAssets' as const,
},
]; ];
const groupByOptions = [ const groupByOptions = [
{ description: 'Category' }, { description: t('Category'), key: 'Category' },
{ description: 'Group' }, { description: t('Group'), key: 'Group' },
{ description: 'Payee' }, { description: t('Payee'), key: 'Payee' },
{ description: 'Account' }, { description: t('Account'), key: 'Account' },
{ description: 'Interval' }, { description: t('Interval'), key: 'Interval' },
]; ];
const sortByOptions: { const sortByOptions: {
description: string; description: string;
key: string;
format: sortByOpType; format: sortByOpType;
}[] = [ }[] = [
{ description: t('Ascending'), format: 'asc' as const }, { description: t('Ascending'), key: 'Ascending', format: 'asc' as const },
{ description: t('Descending'), format: 'desc' as const }, { description: t('Descending'), key: 'Descending', format: 'desc' as const },
{ description: t('Name'), format: 'name' as const }, { description: t('Name'), key: 'Name', format: 'name' as const },
{ description: t('Budget'), format: 'budget' as const }, { description: t('Budget'), key: 'Budget', format: 'budget' as const },
]; ];
export type dateRangeProps = { export type dateRangeProps = {
description: string; description: string;
key: string;
name: number | string; name: number | string;
type?: string; type?: string;
Daily: boolean; Daily: boolean;
@@ -74,6 +84,7 @@ export type dateRangeProps = {
const dateRangeOptions: dateRangeProps[] = [ const dateRangeOptions: dateRangeProps[] = [
{ {
description: t('This week'), description: t('This week'),
key: 'This week',
name: 0, name: 0,
type: 'Week', type: 'Week',
Daily: true, Daily: true,
@@ -83,6 +94,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Last week'), description: t('Last week'),
key: 'Last week',
name: 1, name: 1,
type: 'Week', type: 'Week',
Daily: true, Daily: true,
@@ -92,6 +104,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('This month'), description: t('This month'),
key: 'This month',
name: 0, name: 0,
type: 'Month', type: 'Month',
Daily: true, Daily: true,
@@ -101,6 +114,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Last month'), description: t('Last month'),
key: 'Last month',
name: 1, name: 1,
type: 'Month', type: 'Month',
Daily: true, Daily: true,
@@ -110,6 +124,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Last 3 months'), description: t('Last 3 months'),
key: 'Last 3 months',
name: 3, name: 3,
type: 'Month', type: 'Month',
Daily: true, Daily: true,
@@ -119,6 +134,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Last 6 months'), description: t('Last 6 months'),
key: 'Last 6 months',
name: 6, name: 6,
type: 'Month', type: 'Month',
Daily: false, Daily: false,
@@ -128,6 +144,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Last 12 months'), description: t('Last 12 months'),
key: 'Last 12 months',
name: 12, name: 12,
type: 'Month', type: 'Month',
Daily: false, Daily: false,
@@ -137,6 +154,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Year to date'), description: t('Year to date'),
key: 'Year to date',
name: 'yearToDate', name: 'yearToDate',
type: 'Month', type: 'Month',
Daily: false, Daily: false,
@@ -146,6 +164,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('Last year'), description: t('Last year'),
key: 'Last year',
name: 'lastYear', name: 'lastYear',
type: 'Month', type: 'Month',
Daily: false, Daily: false,
@@ -155,6 +174,7 @@ const dateRangeOptions: dateRangeProps[] = [
}, },
{ {
description: t('All time'), description: t('All time'),
key: 'All time',
name: 'allTime', name: 'allTime',
type: 'Month', type: 'Month',
Daily: false, Daily: false,
@@ -166,6 +186,7 @@ const dateRangeOptions: dateRangeProps[] = [
type intervalOptionsProps = { type intervalOptionsProps = {
description: string; description: string;
key: string;
name: 'Day' | 'Week' | 'Month' | 'Year'; name: 'Day' | 'Week' | 'Month' | 'Year';
format: string; format: string;
range: range:
@@ -178,12 +199,14 @@ type intervalOptionsProps = {
const intervalOptions: intervalOptionsProps[] = [ const intervalOptions: intervalOptionsProps[] = [
{ {
description: t('Daily'), description: t('Daily'),
key: 'Daily',
name: 'Day', name: 'Day',
format: 'yy-MM-dd', format: 'yy-MM-dd',
range: 'dayRangeInclusive', range: 'dayRangeInclusive',
}, },
{ {
description: t('Weekly'), description: t('Weekly'),
key: 'Weekly',
name: 'Week', name: 'Week',
format: 'yy-MM-dd', format: 'yy-MM-dd',
range: 'weekRangeInclusive', range: 'weekRangeInclusive',
@@ -191,6 +214,7 @@ const intervalOptions: intervalOptionsProps[] = [
//{ value: 3, description: 'Fortnightly', name: 3}, //{ value: 3, description: 'Fortnightly', name: 3},
{ {
description: t('Monthly'), description: t('Monthly'),
key: 'Monthly',
name: 'Month', name: 'Month',
// eslint-disable-next-line rulesdir/typography // eslint-disable-next-line rulesdir/typography
format: "MMM ''yy", format: "MMM ''yy",
@@ -198,6 +222,7 @@ const intervalOptions: intervalOptionsProps[] = [
}, },
{ {
description: t('Yearly'), description: t('Yearly'),
key: 'Yearly',
name: 'Year', name: 'Year',
format: 'yyyy', format: 'yyyy',
range: 'yearRangeInclusive', range: 'yearRangeInclusive',
@@ -205,36 +230,29 @@ const intervalOptions: intervalOptionsProps[] = [
]; ];
export const ReportOptions = { export const ReportOptions = {
groupBy: groupByOptions.map(item => item.description), groupBy: groupByOptions,
groupByItems: new Set(groupByOptions.map(item => item.key)),
balanceType: balanceTypeOptions, balanceType: balanceTypeOptions,
balanceTypeMap: new Map( balanceTypeMap: new Map(
balanceTypeOptions.map(item => [item.description, item.format]), balanceTypeOptions.map(item => [item.key, item.format]),
), ),
sortBy: sortByOptions, sortBy: sortByOptions,
sortByMap: new Map( sortByMap: new Map(sortByOptions.map(item => [item.key, item.format])),
sortByOptions.map(item => [item.description, item.format]),
),
dateRange: dateRangeOptions, dateRange: dateRangeOptions,
dateRangeMap: new Map( dateRangeMap: new Map(dateRangeOptions.map(item => [item.key, item.name])),
dateRangeOptions.map(item => [item.description, item.name]), dateRangeType: new Map(dateRangeOptions.map(item => [item.key, item.type])),
),
dateRangeType: new Map(
dateRangeOptions.map(item => [item.description, item.type]),
),
interval: intervalOptions, interval: intervalOptions,
intervalMap: new Map<string, 'Day' | 'Week' | 'Month' | 'Year'>( intervalMap: new Map<string, 'Day' | 'Week' | 'Month' | 'Year'>(
intervalOptions.map(item => [item.description, item.name]), intervalOptions.map(item => [item.key, item.name]),
),
intervalFormat: new Map(
intervalOptions.map(item => [item.description, item.format]),
), ),
intervalFormat: new Map(intervalOptions.map(item => [item.key, item.format])),
intervalRange: new Map< intervalRange: new Map<
string, string,
| 'dayRangeInclusive' | 'dayRangeInclusive'
| 'weekRangeInclusive' | 'weekRangeInclusive'
| 'rangeInclusive' | 'rangeInclusive'
| 'yearRangeInclusive' | 'yearRangeInclusive'
>(intervalOptions.map(item => [item.description, item.range])), >(intervalOptions.map(item => [item.key, item.range])),
}; };
export type QueryDataEntity = { export type QueryDataEntity = {

View File

@@ -156,7 +156,7 @@ export function ReportSidebar({
const rangeOptions = useMemo(() => { const rangeOptions = useMemo(() => {
const options: SelectOption[] = ReportOptions.dateRange const options: SelectOption[] = ReportOptions.dateRange
.filter(f => f[customReportItems.interval as keyof dateRangeProps]) .filter(f => f[customReportItems.interval as keyof dateRangeProps])
.map(option => [option.description, option.description]); .map(option => [option.key, option.description]);
// Append separator if necessary // Append separator if necessary
if (dateRangeLine > 0) { if (dateRangeLine > 0) {
@@ -230,7 +230,10 @@ export function ReportSidebar({
<Select <Select
value={customReportItems.groupBy} value={customReportItems.groupBy}
onChange={e => onChangeSplit(e)} onChange={e => onChangeSplit(e)}
options={ReportOptions.groupBy.map(option => [option, option])} options={ReportOptions.groupBy.map(option => [
option.key,
option.description,
])}
disabledKeys={disabledItems('split')} disabledKeys={disabledItems('split')}
/> />
</View> </View>
@@ -249,7 +252,7 @@ export function ReportSidebar({
value={customReportItems.balanceType} value={customReportItems.balanceType}
onChange={e => onChangeBalanceType(e)} onChange={e => onChangeBalanceType(e)}
options={ReportOptions.balanceType.map(option => [ options={ReportOptions.balanceType.map(option => [
option.description, option.key,
option.description, option.description,
])} ])}
disabledKeys={disabledItems('type')} disabledKeys={disabledItems('type')}
@@ -274,14 +277,14 @@ export function ReportSidebar({
if ( if (
ReportOptions.dateRange ReportOptions.dateRange
.filter(d => !d[e as keyof dateRangeProps]) .filter(d => !d[e as keyof dateRangeProps])
.map(int => int.description) .map(int => int.key)
.includes(customReportItems.dateRange) .includes(customReportItems.dateRange)
) { ) {
onSelectRange(defaultsList.intervalRange.get(e) || ''); onSelectRange(defaultsList.intervalRange.get(e) || '');
} }
}} }}
options={ReportOptions.interval.map(option => [ options={ReportOptions.interval.map(option => [
option.description, option.key,
option.description, option.description,
])} ])}
disabledKeys={[]} disabledKeys={[]}

View File

@@ -5,18 +5,22 @@ import { type sortByOpType } from 'loot-core/types/models';
const intervalOptions = [ const intervalOptions = [
{ {
description: t('Daily'), description: t('Daily'),
key: 'Daily',
defaultRange: 'This month', defaultRange: 'This month',
}, },
{ {
description: t('Weekly'), description: t('Weekly'),
key: 'Weekly',
defaultRange: 'Last 3 months', defaultRange: 'Last 3 months',
}, },
{ {
description: t('Monthly'), description: t('Monthly'),
key: 'Monthly',
defaultRange: 'Last 6 months', defaultRange: 'Last 6 months',
}, },
{ {
description: t('Yearly'), description: t('Yearly'),
key: 'Yearly',
defaultRange: 'Year to date', defaultRange: 'Year to date',
}, },
]; ];
@@ -215,6 +219,6 @@ export const defaultsList = {
modeOptions.map(item => [item.description, item.defaultGraph]), modeOptions.map(item => [item.description, item.defaultGraph]),
), ),
intervalRange: new Map( intervalRange: new Map(
intervalOptions.map(item => [item.description, item.defaultRange]), intervalOptions.map(item => [item.key, item.defaultRange]),
), ),
}; };

View File

@@ -524,7 +524,7 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
}; };
const defaultItems = (item: string) => { const defaultItems = (item: string) => {
const chooseGraph = ReportOptions.groupBy.includes(item) ? graphType : item; const chooseGraph = ReportOptions.groupByItems.has(item) ? graphType : item;
if ( if (
(disabledGraphList(mode, chooseGraph, 'disabledSplit') || []).includes( (disabledGraphList(mode, chooseGraph, 'disabledSplit') || []).includes(
groupBy, groupBy,

View File

@@ -59,7 +59,7 @@ export function LanguageSettings() {
variant="external" variant="external"
to={ to={
'https://hosted.weblate.org/projects/actualbudget/actual/' + 'https://hosted.weblate.org/projects/actualbudget/actual/' +
language (language ?? '')
} }
linkColor="purple" linkColor="purple"
> >

View File

@@ -77,5 +77,9 @@ export const setI18NextLanguage = (language: string) => {
return; return;
} }
if (language === i18n.language) {
return; // language is already set
}
i18n.changeLanguage(language || 'en'); i18n.changeLanguage(language || 'en');
}; };

View File

@@ -3,7 +3,7 @@
"author": "Actual", "author": "Actual",
"productName": "Actual", "productName": "Actual",
"description": "A simple and powerful personal finance system", "description": "A simple and powerful personal finance system",
"version": "25.2.0", "version": "25.2.1",
"scripts": { "scripts": {
"clean": "rm -rf dist", "clean": "rm -rf dist",
"update-client": "bin/update-client", "update-client": "bin/update-client",

View File

@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [jfdoming]
---
Fix crashes on reports page with translations enabled

View File

@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [matt-fidd]
---
Fix broken Weblate URL in settings if the language option has never been set

View File

@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [MikesGlitch]
---
Fix Electron language support