Files
FreshRSS/Makefile
Christian Weiske 1acc646222 Show time since when a feed has problems + new timeago() method and i18n plurals (#8670)
Closes https://github.com/FreshRSS/FreshRSS/issues/8508

Changes proposed in this pull request:

- Use an integer for `Feed::error` everywhere (follow up to #8646)
- Extract `Entry::machineReadableDate()` into function for use in HTML templates
- Add `timeago()` function that converts a unix timestamp into a "4 weeks ago" string
- Show the last successful feed update, and the last erroneous update

How to test the feature manually:

1. Update a feed
2. Modify the feed URL in the database and set it to a non-existing URL
3. Update the feed again
4. Open the "Manage feed" and see the expanded error message:

>  Blast! This feed has encountered a problem. If this situation persists, please verify that it is still reachable.
> Last successful update 3 hours ago, last erroneous update 1 hour ago. 

You can hover the relative dates to see the timestamp.

* Make Feed::error an int everywhere

Related: https://github.com/FreshRSS/FreshRSS/pull/8646

* Extract timestamptomachinedate()

.. for later usage in the feed error time display.

* Show time since when a feed has problems

We add our own "timeago" function that converts a unix timestamp
into a "4 weeks ago" string.

Resolves: https://github.com/FreshRSS/FreshRSS/issues/8508

* Add new translation keys

* i18n fr, en-US

* Minor XHTML preference

* Slightly shorter rewrite, also hopefully easier to read

* Rewrite to allow (simple) plural
I also moved some functions around for hopefully a more generic and better structure.
I made some changes for the sake of speed (e.g. second-based logic instead of datetime intervals).
Note: I used automatic translation as I was worried it would be too complicated to explain to translators... I proofread the few languages I have some familiarity with.

* Add reference to CLDR

* Slightly more compact syntax

* Always show last update, fix case of unknown error date

* Remove forgotten span

* No need for multi-lines anymore

* Fix error date thresshold

* plurals forms

* Extract gettext formula conversion script to cli

* Simplify a bit

* Escort excess parentheses to the door

* Simplify

* Avoid being too clever in localization

* Fix German

* Fix plural TODO parsing

* Ignore en-US translation

* make fix-all

* git update-index --chmod=+x cli/compile.plurals.php

* Heredoc indent PHP 7.3+

* compileAll: Continue on error

* PHP strict comparisons

* Light logical simplification

* Cache plural_message_families

* Avoid case of empty value

* A bit of documentation

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Co-authored-by: Frans de Jonge <frans@clevercast.com>
Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>
2026-04-07 22:56:02 +02:00

248 lines
7.2 KiB
Makefile

.DEFAULT_GOAL := help
ifndef TAG
TAG=alpine
endif
PORT ?= 8080
NETWORK ?= freshrss-network
# detect docker or podman
DOCKER ?= $(shell which docker 2>/dev/null || which podman 2>/dev/null)
ifeq ($(DOCKER),)
NO_DOCKER := 1
endif
ifdef NO_DOCKER
PHP = $(shell which php)
else
PHP = $(DOCKER) run \
--rm \
--volume $(shell pwd):/var/www/FreshRSS:z \
--env FRESHRSS_ENV=development \
--name freshrss-php-cli \
docker.io/freshrss/freshrss:$(TAG) \
php
endif
ifeq ($(findstring alpine,$(TAG)),alpine)
DOCKERFILE=Dockerfile-Alpine
else
DOCKERFILE=Dockerfile
endif
##@ Docker
.PHONY: build
build: ## Build a Docker image
$(DOCKER) build \
--pull \
--tag freshrss/freshrss:$(TAG) \
--file Docker/$(DOCKERFILE) .
.PHONY: start
start: ## Start the development environment (use Docker)
$(DOCKER) network create --driver bridge $(NETWORK) || true
$(foreach extension,$(extensions),$(eval volumes=$(volumes) --volume $(extension):/var/www/FreshRSS/extensions/$(notdir $(extension)):z))
$(DOCKER) run \
-it \
--rm \
--volume $(shell pwd):/var/www/FreshRSS:z \
$(volumes) \
--publish $(PORT):80 \
--env FRESHRSS_ENV=development \
--name freshrss-dev \
--network $(NETWORK) \
docker.io/freshrss/freshrss:$(TAG)
.PHONY: stop
stop: ## Stop FreshRSS container if any
$(DOCKER) stop freshrss-dev || true
$(DOCKER) network rm $(NETWORK) || true
##@ Tests and linter
.PHONY: lint
lint: bin/phpcs ## Run the linter on PHP files
$(PHP) bin/phpcs . -p -s
.PHONY: lint-fix
lint-fix: bin/phpcbf ## Fix the errors detected by the linter
$(PHP) bin/phpcbf . -p -s
.PHONY: test
test: bin/phpunit ## Run the PHP test suite
$(PHP) bin/phpunit --bootstrap ./tests/bootstrap.php ./tests
bin/composer:
mkdir -p bin/
wget 'https://raw.githubusercontent.com/composer/getcomposer.org/a5abae68b349213793dca4a1afcaada0ad11143b/web/installer' -O - -q | php -- --quiet --install-dir='./bin/' --filename='composer'
# building any of these builds them all
vendor/bin/phpunit vendor/bin/phpcs vendor/bin/phpcbf vendor/bin/phpstan &: bin/composer
bin/composer install --prefer-dist --no-progress
# Any of these depend on the vendor/ target, and then symlink the vendor/bin/ to the bin/.
# use -sf so if the symlink already exists it won't error out. Running this from a container often won't properly detect it already exists
bin/phpunit bin/phpcs bin/phpcbf bin/phpstan : % : vendor/%
ln -sf $< $@
bin/typos:
mkdir -p bin/
cd bin ; \
wget -q 'https://github.com/crate-ci/typos/releases/download/v1.29.9/typos-v1.29.9-x86_64-unknown-linux-musl.tar.gz' && \
tar -xvf *.tar.gz './typos' && \
chmod +x typos && \
rm *.tar.gz ; \
cd ..
node_modules/.bin/eslint:
npm install
node_modules/.bin/rtlcss:
npm install
# TODO: Add composer install
.PHONY: composer-test
composer-test: bin/phpstan bin/composer
bin/composer run-script test
.PHONY: composer-fix
composer-fix: bin/composer
bin/composer run-script fix
.PHONY: npm-test
npm-test: node_modules/.bin/eslint
npm test
.PHONY: npm-fix
npm-fix: node_modules/.bin/eslint
npm run fix
.PHONY: typos-test
typos-test: bin/typos
bin/typos
# TODO: Add shellcheck, shfmt, hadolint
.PHONY: test-all
test-all: composer-test npm-test typos-test ## Run all tests
.PHONY: fix-all
fix-all: composer-fix npm-fix ## Run all fixes
##@ I18n
.PHONY: i18n-add-file
i18n-add-file: ## Add a new translation file to all supported languages
ifndef key
$(error To add a new file, you need to provide one in the "key" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action add --key $(key)
@echo File added.
.PHONY: i18n-add-key
i18n-add-key: ## Add a translation key to all supported languages
ifndef key
$(error To add a key, you need to provide one in the "key" variable)
endif
ifndef value
$(error To add a key, you need to provide its value in the "value" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action add --key $(key) --value "$(value)"
@echo Key added.
.PHONY: i18n-move-key
i18n-move-key: ## Move an existing key into a new location
ifndef key
$(error To move a key, you need to provide one in the "key" variable)
endif
ifndef new-key
$(error To specify a location to move the key to, you need to provide it in the "new-key" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action move --key $(key) --new-key "$(new-key)"
@echo Key moved.
.PHONY: i18n-add-language
i18n-add-language: ## Add a new supported language
ifndef lang
$(error To add a new language, you need to provide one in the "lang" variable)
endif
$(PHP) ./cli/manipulate.translation.php --action add --language $(lang) --origin-language $(ref)
@echo Language added.
.PHONY: i18n-compile-plurals
i18n-compile-plurals: ## Compile plural formulas from app/i18n/*/plurals.php
@$(PHP) ./cli/compile.plurals.php --all
@echo Plural files compiled.
.PHONY: i18n-format
i18n-format: ## Format I18N files
@$(PHP) ./cli/manipulate.translation.php --action format
@$(PHP) ./cli/compile.plurals.php --all
@echo Files formatted.
.PHONY: i18n-ignore-key
i18n-ignore-key: ## Ignore a translation key for the selected language
ifndef lang
$(error To ignore a key, you need to provide a language in the "lang" variable)
endif
ifndef key
$(error To ignore a key, you need to provide one in the "key" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action ignore --key $(key) --language $(lang)
@echo Key ignored.
.PHONY: i18n-ignore-unmodified-keys
i18n-ignore-unmodified-keys: ## Ignore all unmodified translation keys for the selected language
ifndef lang
$(error To ignore unmodified keys, you need to provide a language in the "lang" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action ignore_unmodified --language $(lang)
@echo Unmodified keys ignored.
.PHONY: i18n-key-exists
i18n-key-exists: ## Check if a translation key exists
ifndef key
$(error To check if a key exists, you need to provide one in the "key" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action exist --key $(key)
.PHONY: i18n-remove-key
i18n-remove-key: ## Remove a translation key from all supported languages
ifndef key
$(error To remove a key, you need to provide one in the "key" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action delete --key $(key)
@echo Key removed.
.PHONY: i18n-update-key
i18n-update-key: ## Update a translation key in all supported languages
ifndef key
$(error To update a key, you need to provide one in the "key" variable)
endif
ifndef value
$(error To update a key, you need to provide its value in the "value" variable)
endif
@$(PHP) ./cli/manipulate.translation.php --action add --key $(key) --value "$(value)" --language en
@echo Key updated.
##@ Tools
.PHONY: pot
pot: ## Generate POT templates for docs
cd docs && ../cli/translation-update.sh
.PHONY: readme
readme: ## Generate translation progress in README file
@$(PHP) ./cli/check.translation.php --generate-readme
.PHONY: refresh
refresh: ## Refresh feeds by fetching new messages
@$(PHP) ./app/actualize_script.php
.PHONY: rtl
rtl: node_modules/.bin/rtlcss ## Generate RTL CSS files
npm run-script rtlcss
##@ Help
.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-30s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)