Select Your Language
{{ currentSubtitle }}
English
ગુજરાતી
(Gujarati)
हिन्दी
(Hindi)
ಕನ್ನಡ
(Kannada)
తెలుగు
(Telugu)
मराठी
(Marathi)
বাংলা - সাধু
(Bengali Sadhu)
বাংলা - চলিত
(Bengali Cholito)
தமிழ்
(Tamil)
മലയാളം
(Malayalam)
ਪੰਜਾਬੀ
(Punjabi)
ଓଡ଼ିଆ
(Odia)
অসমীয়া
(Assamese)
भोजपुरी
(Bhojpuri)
मैथिली
(Maithili)
अवधी
(Awadhi)
{{ progressState.title }}
{{ progressState.message }}
{{ i18n.t('cancel') }}
⚠ {{ i18n.t('urlOverflowBanner') || 'The shared link could not encode all inputs (too long). Calculator opened in default state.' }}
✕
{{ i18n.t('whatIsPpm') }}
{{ i18n.t('theBasicFormula') }}
{{ i18n.t('breakDownEachPart') }}
{{ i18n.t('noCalculationYet') }}
{{ i18n.t('addFertilizersToSeeBreakdown') }}
{{ i18n.t('calculatorShowsStepByStep') }}
{{ i18n.t('yourCurrentCalculation') }}
{{ i18n.t('solutionVolumeLabel') }} {{ formatNumber(modalData.volume) }} {{ i18n.t('litersUnit') }}
{{ i18n.t('fertilizersUsedLabel') }} {{ modalData.activeFertilizers.length }}
{{ i18n.t('stepByStepBreakdown') }}
{{ i18n.t('howEachFertilizerContributesToPpm') }}
{{ index + 1 }}
{{ i18n.getFertilizerName(fert) }}
{{ i18n.t('amountUsedLabel') }} {{ formatNumber(fert.grams) }} {{ i18n.t('gramsUnit') }}
{{ i18n.t('nutrientPpmValues') }}:
{{ nutrient.name }}
{{ formatNumber(nutrient.ppm, 2) }} ppm
{{ formatNumber(fert.grams) }} g × {{ formatNumber(1000) }} × ({{ formatNumber(nutrient.percent, 2) }}% ÷ {{ formatNumber(100) }}) ÷ {{ formatNumber(modalData.volume) }} {{ i18n.t('litersUnit') }} = {{ formatNumber(nutrient.ppm, 2) }} ppm
{{ i18n.t('aboutOxideConversions') }}
{{ i18n.t('oxideFormHeader') }}
{{ i18n.t('elementalFormHeader') }}
{{ i18n.t('conversionFactorHeader') }}
{{ conv.oxideName }}
{{ conv.elementalName }}
× {{ conv.factor }}
{{ i18n.t('quickTips') }}
{{ i18n.t('tip1PpmEquals') }}
{{ i18n.t('tip2StartLower') }}
{{ i18n.t('tip3DifferentPlants') }}
{{ i18n.t('tip4BalanceIsKey') }}
{{ i18n.t('whatIsIonBalance') }}
{{ i18n.t('understandingMeqL') }}
{{ i18n.t('meqLAnalogy') }}
{{ i18n.t('noCalculationYet') }}
{{ i18n.t('addFertilizersForIonBalance') }}
{{ i18n.t('yourCurrentSolution') }}
{{ i18n.t('solutionVolumeLabel') }} {{ formatNumber(modalData.volume) }} {{ i18n.t('litersUnit') }}
{{ i18n.t('fertilizersUsedLabel') }} {{ modalData.activeFertilizers.length }}
{{ i18n.t('stepByStepIonCalculation') }}
{{ i18n.t('howEachFertilizerContributesIons') }}
{{ index + 1 }}
{{ i18n.getFertilizerName(fert) }}
{{ i18n.t('amountUsedLabel') }} {{ formatNumber(fert.grams) }} {{ i18n.t('gramsUnit') }}
{{ i18n.t('molarMassLabel') }} {{ formatNumber(getIonDataForFert(fert).molarMass, 2) }} g/mol
{{ i18n.t('molesLabel') }} {{ formatNumber(fert.grams) }} g ÷ {{ formatNumber(getIonDataForFert(fert).molarMass, 2) }} g/mol = {{ formatNumber(fert.grams / getIonDataForFert(fert).molarMass, 6) }} mol
Ion Contributions:
{{ ionInfo.ion }} ({{ ionInfo.type === 'cation' ? '+' : '-' }})
{{ formatNumber(calculateIonMeq(fert, ionInfo), 3) }} meq/L
{{ formatNumber(fert.grams / getIonDataForFert(fert).molarMass, 6) }} mol × {{ formatNumber(ionInfo.count) }} {{ i18n.t('ionsUnit') }} × {{ formatNumber(ionInfo.charge) }} {{ i18n.t('chargeUnit') }} × {{ formatNumber(1000) }} ÷ {{ formatNumber(modalData.volume) }} {{ i18n.t('litersUnit') }} = {{ formatNumber(calculateIonMeq(fert, ionInfo), 3) }} meq/L
Cations subtotal:
{{ formatNumber(calculateFertCationTotal(fert), 3) }} meq/L
Anions subtotal:
{{ formatNumber(calculateFertAnionTotal(fert), 3) }} meq/L
{{ i18n.t('nutrientTotalsSummary') }}
{{ i18n.t('whenNutrientsFromMultiple') }}
{{ i18n.t('cations') }} (+)
{{ ion }}
{{ formatNumber(data.meq, 3) }} meq/L
{{ i18n.t('totalCations') }}
{{ formatNumber(modalData.ionBalance.totalCations, 3) }} meq/L
{{ i18n.t('anions') }} (-)
{{ ion }}
{{ formatNumber(data.meq, 3) }} meq/L
{{ i18n.t('totalAnions') }}
{{ formatNumber(modalData.ionBalance.totalAnions, 3) }} meq/L
{{ i18n.t('finalIonBalanceResults') }}
{{ i18n.t('totalCationsPlus') }}
{{ formatNumber(modalData.ionBalance.totalCations, 3) }} meq/L
vs
{{ i18n.t('totalAnionsMinus') }}
{{ formatNumber(modalData.ionBalance.totalAnions, 3) }} meq/L
{{ i18n.t('imbalancePercentage') }}
{{ formatNumber(modalData.ionBalance.imbalance, 1) }}%
{{ modalData.ionBalance.statusText }}
{{ i18n.t('howWeCalculatedImbalance') }}
|{{ formatNumber(modalData.ionBalance.totalCations, 3) }} - {{ formatNumber(modalData.ionBalance.totalAnions, 3) }}| ÷ (({{ formatNumber(modalData.ionBalance.totalCations, 3) }} + {{ formatNumber(modalData.ionBalance.totalAnions, 3) }}) ÷ 2) × 100 = {{ formatNumber(modalData.ionBalance.imbalance, 1) }}%
{{ i18n.t('interpretingResults') }}
{{ i18n.t('imbalanceLessThan10') }} {{ i18n.t('imbalanceLessThan10Desc') }}
{{ i18n.t('imbalance10To20') }} {{ i18n.t('imbalance10To20Desc') }}
{{ i18n.t('imbalanceOver20') }} {{ i18n.t('imbalanceOver20Desc') }}
{{ i18n.t('whyDoesThisMatter') }} {{ i18n.t('whyDoesThisMatterExplanation') }}
{{ i18n.t('ecCalculationMethod') }}
{{ i18n.t('lambdaReferenceTable') }}
{{ i18n.t('lambdaTableDescription') }}
{{ i18n.t('cations') }} (+)
{{ i18n.t('ionHeader') }}
{{ i18n.t('molarMassHeader') }}
λ
K⁺ ({{ i18n.t('potassium') }}) {{ formatNumber(39.098) }} {{ formatNumber(73.5) }}
NH₄⁺ ({{ i18n.t('ammonium') }}) {{ formatNumber(14.007) }} {{ formatNumber(73.5) }}
Ca²⁺ ({{ i18n.t('calciumSimple') }}) {{ formatNumber(40.078) }} {{ formatNumber(119.0) }}
Mg²⁺ ({{ i18n.t('magnesiumSimple') }}) {{ formatNumber(24.305) }} {{ formatNumber(106.0) }}
Fe²⁺ ({{ i18n.t('ironII') }}) {{ formatNumber(55.845) }} {{ formatNumber(108.0) }}
Fe³⁺ ({{ i18n.t('ironIII') }}) {{ formatNumber(55.845) }} {{ formatNumber(204.0) }}
Mn²⁺ ({{ i18n.t('manganese') }}) {{ formatNumber(54.938) }} {{ formatNumber(107.0) }}
Zn²⁺ ({{ i18n.t('zinc') }}) {{ formatNumber(65.38) }} {{ formatNumber(105.6) }}
Cu²⁺ ({{ i18n.t('copper') }}) {{ formatNumber(63.546) }} {{ formatNumber(107.2) }}
{{ i18n.t('anions') }} (-)
{{ i18n.t('ionHeader') }}
{{ i18n.t('molarMassHeader') }}
λ
NO₃⁻ ({{ i18n.t('nitrate') }}) {{ formatNumber(14.007) }} {{ formatNumber(71.5) }}
Cl⁻ ({{ i18n.t('chloride') }}) {{ formatNumber(35.453) }} {{ formatNumber(76.3) }}
SO₄²⁻ ({{ i18n.t('sulfate') }}) {{ formatNumber(32.065) }} {{ formatNumber(160.0) }}
H₂PO₄⁻ ({{ i18n.t('dihydrogenPhosphate') }}) {{ formatNumber(30.974) }} {{ formatNumber(33.5) }}
HPO₄²⁻ ({{ i18n.t('hydrogenPhosphate') }}) {{ formatNumber(30.974) }} {{ formatNumber(114.0) }}
HCO₃⁻ ({{ i18n.t('bicarbonate') }}) {{ formatNumber(61.017) }} {{ formatNumber(44.5) }}
{{ i18n.t('lambdaUnitsNote') }}
{{ i18n.t('ecRangesTitle') }}
< 1.0 mS/cm: {{ i18n.t('ecRangeLow') }}
1.0 - 1.5 mS/cm: {{ i18n.t('ecRangeMild') }}
1.5 - 2.5 mS/cm: {{ i18n.t('ecRangeOptimal') }}
2.5 - 3.0 mS/cm: {{ i18n.t('ecRangeStrong') }}
> 3.0 mS/cm: {{ i18n.t('ecRangeHigh') }}
{{ i18n.t('ecBreakdownByIon') }}
{{ i18n.t('ecBreakdownDescription') }}
{{ i18n.t('tableColumnsExplained') }}:
{{ i18n.t('ionHeader') }} - {{ i18n.t('ionColumnDesc') }}
{{ i18n.t('concMmolLHeader') }} - {{ i18n.t('concColumnDesc') }}
λ ({{ i18n.t('lambdaHeader') }}) - {{ i18n.t('lambdaColumnDesc') }}
{{ i18n.t('ecContribHeader') }} - {{ i18n.t('contribColumnDesc') }}
{{ i18n.t('howConcentrationCalculated') }}:
{{ i18n.t('concentrationFormula') }}
{{ i18n.t('concentrationFormulaDesc') }}
{{ i18n.t('ppmLearnMoreNote') }}
{{ i18n.t('ionHeader') }}
PPM
{{ i18n.t('concentrationCalcHeader') }}
λ
{{ i18n.t('ecContribHeader') }}
%
{{ ion }}
{{ data.ppm ? i18n.formatNumber(data.ppm.toFixed(2)) : '-' }}
{{ i18n.formatNumber(data.ppm.toFixed(2)) }} ÷ {{ i18n.formatNumber(data.molarMass.toFixed(3)) }} = {{ i18n.formatNumber(data.concentration_mmolL.toFixed(3)) }}
{{ i18n.formatNumber(data.concentration_mmolL.toFixed(3)) }}
{{ i18n.formatNumber(data.lambda) }}
{{ i18n.formatNumber(data.contribution_mS_cm.toFixed(4)) }}
{{ i18n.formatNumber((data.contribution_mS_cm / modalData.rawEC * 100).toFixed(1)) }}%
{{ i18n.t('totalLabel') }}
{{ i18n.formatNumber(modalData.rawEC?.toFixed(4) || 0) }} mS/cm
{{ formatNumber(100) }}%
{{ i18n.t('howEachRowCalculated') }}:
{{ i18n.t('ecContribFormula') }}
{{ i18n.t('ecContribFormulaDesc') }}
{{ i18n.t('rawEcLabel') }}: {{ i18n.formatNumber(modalData.rawEC?.toFixed(3) || 0) }} mS/cm
{{ i18n.t('ionicStrength') }}: {{ i18n.formatNumber(modalData.ionicStrength?.toFixed(4) || 0) }} mol/L
{{ i18n.t('ionicStrengthCorrectionNote') }}
{{ i18n.t('ecTips') }}
{{ i18n.t('ecTip1') }}
{{ i18n.t('ecTip2') }}
{{ i18n.t('ecTip3') }}
{{ i18n.t('ecTip4') }}
{{ i18n.t('whatIsKCaRatio') }}
{{ i18n.t('kCaYourCurrentRatio') }}
{{ i18n.formatNumber(modalData.kCaRatio) }} : 1
{{ modalData.kCaStatus.text }}
{{ i18n.t('kCaOptimalRange') }}
{{ i18n.t('kCaContextualWarning') }}
{{ i18n.t('kCaWhenTooHigh') }}
{{ i18n.t('kCaHighSymptoms') }}
{{ i18n.t('kCaHighSymptom1') }}
{{ i18n.t('kCaHighSymptom2') }}
{{ i18n.t('kCaHighSymptom3') }}
{{ i18n.t('kCaHighCauses') }}
{{ i18n.t('kCaHighCause1') }}
{{ i18n.t('kCaHighCause2') }}
{{ i18n.t('kCaHighFixes') }}
{{ i18n.t('kCaHighFix2') }}
{{ i18n.t('kCaHighFixWarning') }}
{{ i18n.t('kCaWhenTooLow') }}
{{ i18n.t('kCaLowSymptoms') }}
{{ i18n.t('kCaLowSymptom1') }}
{{ i18n.t('kCaLowSymptom2') }}
{{ i18n.t('kCaLowCauses') }}
{{ i18n.t('kCaLowCause1') }}
{{ i18n.t('kCaLowCause2') }}
{{ i18n.t('kCaLowFixes') }}
{{ i18n.t('kCaLowFix1') }}
{{ i18n.t('kCaLowFix2') }}
{{ i18n.t('kCaCommonMistakes') }}
{{ i18n.t('kCaMistake1Title') }}
{{ i18n.t('kCaMistake1Why') }}
{{ i18n.t('kCaMistake2Title') }}
{{ i18n.t('kCaMistake2Why') }}
{{ i18n.t('kCaMistake3Title') }}
{{ i18n.t('kCaMistake3Why') }}
{{ i18n.t('kCaWhenToAdjust') }}
{{ i18n.t('kCaIncreaseKWhen') }}
{{ i18n.t('kCaIncreaseK1') }}
{{ i18n.t('kCaIncreaseK2') }}
{{ i18n.t('kCaIncreaseCaWhen') }}
{{ i18n.t('kCaIncreaseCa1') }}
{{ i18n.t('kCaIncreaseCa2') }}
{{ i18n.t('kCaReduceKWhen') }}
{{ i18n.t('kCaReduceK1') }}
{{ i18n.t('kCaRealityCheck') }}
{{ i18n.t('kCaRealityCheckText') }}
{{ i18n.t('kCaRealityCheck1') }}
{{ i18n.t('kCaRealityCheck2') }}
{{ i18n.t('kCaRealityCheck3') }}
{{ i18n.t('kCaRealityCheckConclusion') }}
{{ i18n.t('whatIsNo3Nh4Ratio') }}
{{ i18n.t('no3Nh4YourCurrentRatio') }}
{{ i18n.formatNumber(modalData.no3Nh4Ratio?.toFixed(1) || '0') }} : 1
{{ modalData.no3Nh4Status.text }}
{{ i18n.t('no3Nh4OptimalRange') }}
{{ i18n.t('no3Nh4ContextualWarning') }}
{{ i18n.t('no3Nh4YourCurrentRatio') }}
100% NO₃
{{ i18n.t('no3Nh4StatusVeryHigh') }}
{{ i18n.t('no3Nh4VeryHighNote') }}
{{ i18n.t('no3Nh4ThresholdsTitle') }}
{{ i18n.t('no3Nh4Threshold1') }}
{{ i18n.t('no3Nh4Threshold2') }}
{{ i18n.t('no3Nh4Threshold3') }}
{{ i18n.t('no3Nh4Threshold4') }}
{{ i18n.t('no3Nh4WhenTooLow') }}
{{ i18n.t('no3Nh4LowSymptoms') }}
{{ i18n.t('no3Nh4LowSymptom1') }}
{{ i18n.t('no3Nh4LowSymptom2') }}
{{ i18n.t('no3Nh4LowSymptom3') }}
{{ i18n.t('no3Nh4LowSymptom4') }}
{{ i18n.t('no3Nh4LowCauses') }}
{{ i18n.t('no3Nh4LowCause1') }}
{{ i18n.t('no3Nh4LowCause2') }}
{{ i18n.t('no3Nh4LowCause3') }}
{{ i18n.t('no3Nh4LowFixes') }}
{{ i18n.t('no3Nh4LowFixWarning') }}
{{ i18n.t('no3Nh4LowWhenToAct') }}
{{ i18n.t('no3Nh4WhenVeryHigh') }}
{{ i18n.t('no3Nh4VeryHighNote') }}
{{ i18n.t('no3Nh4VeryHighSymptoms') }}
{{ i18n.t('no3Nh4VeryHighSymptom1') }}
{{ i18n.t('no3Nh4VeryHighSymptom2') }}
{{ i18n.t('no3Nh4VeryHighSymptom3') }}
{{ i18n.t('no3Nh4VeryHighCauses') }}
{{ i18n.t('no3Nh4VeryHighCause1') }}
{{ i18n.t('no3Nh4VeryHighFixes') }}
{{ i18n.t('no3Nh4VeryHighFix1') }}
{{ i18n.t('no3Nh4VeryHighFix2') }}
{{ i18n.t('no3Nh4VeryHighWhenToAct') }}
{{ i18n.t('no3Nh4CommonMistakes') }}
{{ i18n.t('no3Nh4Mistake1Title') }}
{{ i18n.t('no3Nh4Mistake1Why') }}
{{ i18n.t('no3Nh4Mistake2Title') }}
{{ i18n.t('no3Nh4Mistake2Why') }}
{{ i18n.t('no3Nh4Mistake3Title') }}
{{ i18n.t('no3Nh4Mistake3Why') }}
{{ i18n.t('no3Nh4TimingTitle') }}
{{ i18n.t('no3Nh4PreferNitrate') }}
{{ i18n.t('no3Nh4PreferNitrate1') }}
{{ i18n.t('no3Nh4PreferNitrate2') }}
{{ i18n.t('no3Nh4PreferNitrate3') }}
{{ i18n.t('no3Nh4AllowNh4') }}
{{ i18n.t('no3Nh4AllowNh41') }}
{{ i18n.t('no3Nh4AllowNh42') }}
{{ i18n.t('no3Nh4AllowNh43') }}
{{ i18n.t('no3Nh4RealityCheck') }}
{{ i18n.t('no3Nh4RealityCheckText') }}
{{ i18n.t('no3Nh4RealityCheck1') }}
{{ i18n.t('no3Nh4RealityCheck2') }}
{{ i18n.t('no3Nh4RealityCheck3') }}
{{ i18n.t('no3Nh4RealityCheck4') }}
{{ i18n.t('no3Nh4RealityCheckConclusion') }}
{{ i18n.t('whatIsNKRatio') }}
{{ i18n.t('nkYourCurrentRatio') }}
{{ i18n.formatNumber(modalData.nkRatio?.toFixed(2) || '0') }} : 1
{{ modalData.nkStatus.text }}
{{ i18n.t('nkOptimalRange') }}
{{ i18n.t('nkContextualWarning') }}
{{ i18n.t('nkThresholdsTitle') }}
{{ i18n.t('nkThreshold1') }}
{{ i18n.t('nkThreshold2') }}
{{ i18n.t('nkThreshold3') }}
{{ i18n.t('nkThreshold4') }}
{{ i18n.t('nkThreshold5') }}
{{ i18n.t('nkWhenTooHigh') }}
{{ i18n.t('nkHighSymptoms') }}
{{ i18n.t('nkHighSymptom1') }}
{{ i18n.t('nkHighSymptom2') }}
{{ i18n.t('nkHighSymptom3') }}
{{ i18n.t('nkHighCauses') }}
{{ i18n.t('nkHighCause1') }}
{{ i18n.t('nkHighCause2') }}
{{ i18n.t('nkHighFixes') }}
{{ i18n.t('nkHighFixWarning') }}
{{ i18n.t('nkHighWhenToAct') }}
{{ i18n.t('nkWhenTooLow') }}
{{ i18n.t('nkLowSymptoms') }}
{{ i18n.t('nkLowSymptom1') }}
{{ i18n.t('nkLowSymptom2') }}
{{ i18n.t('nkLowSymptom3') }}
{{ i18n.t('nkLowSymptom4') }}
{{ i18n.t('nkLowCauses') }}
{{ i18n.t('nkLowCause1') }}
{{ i18n.t('nkLowCause2') }}
{{ i18n.t('nkLowFixes') }}
{{ i18n.t('nkLowFix3') }}
{{ i18n.t('nkLowFixWarning') }}
{{ i18n.t('nkLowWhenToAct') }}
{{ i18n.t('nkCommonMistakes') }}
{{ i18n.t('nkMistake1Title') }}
{{ i18n.t('nkMistake1Why') }}
{{ i18n.t('nkMistake2Title') }}
{{ i18n.t('nkMistake2Why') }}
{{ i18n.t('nkMistake3Title') }}
{{ i18n.t('nkMistake3Why') }}
{{ i18n.t('nkTimingTitle') }}
{{ i18n.t('nkPreferHigherNK') }}
{{ i18n.t('nkPreferHigherNK1') }}
{{ i18n.t('nkPreferHigherNK2') }}
{{ i18n.t('nkPreferHigherNK3') }}
{{ i18n.t('nkPreferLowerNK') }}
{{ i18n.t('nkPreferLowerNK1') }}
{{ i18n.t('nkPreferLowerNK2') }}
{{ i18n.t('nkPreferLowerNK3') }}
{{ i18n.t('nkRealityCheck') }}
{{ i18n.t('nkRealityCheckText') }}
{{ i18n.t('nkRealityCheck1') }}
{{ i18n.t('nkRealityCheck2') }}
{{ i18n.t('nkRealityCheck3') }}
{{ i18n.t('nkRealityCheck4') }}
{{ i18n.t('nkRealityCheckConclusion') }}
{{ i18n.t('whatIsCaMgRatio') }}
{{ i18n.t('caMgYourCurrentRatio') }}
{{ i18n.formatNumber(modalData.caMgRatio?.toFixed(2) || '0') }} : 1
{{ modalData.caMgStatus.text }}
{{ i18n.t('caMgOptimalRange') }}
{{ i18n.t('caMgContextualWarning') }}
{{ i18n.t('caMgThresholdsTitle') }}
{{ i18n.t('caMgThreshold1') }}
{{ i18n.t('caMgThreshold2') }}
{{ i18n.t('caMgThreshold3') }}
{{ i18n.t('caMgThreshold4') }}
{{ i18n.t('caMgWhenTooHigh') }}
{{ i18n.t('caMgHighSymptoms') }}
{{ i18n.t('caMgHighSymptom1') }}
{{ i18n.t('caMgHighSymptom2') }}
{{ i18n.t('caMgHighSymptom3') }}
{{ i18n.t('caMgHighCauses') }}
{{ i18n.t('caMgHighCause1') }}
{{ i18n.t('caMgHighCause2') }}
{{ i18n.t('caMgHighCause3') }}
{{ i18n.t('caMgHighFixes') }}
{{ i18n.t('caMgHighFix2') }}
{{ i18n.t('caMgHighFixWarning') }}
{{ i18n.t('caMgHighWhenToAct') }}
{{ i18n.t('caMgWhenTooLow') }}
{{ i18n.t('caMgLowSymptoms') }}
{{ i18n.t('caMgLowSymptom1') }}
{{ i18n.t('caMgLowSymptom2') }}
{{ i18n.t('caMgLowSymptom3') }}
{{ i18n.t('caMgLowSymptom4') }}
{{ i18n.t('caMgLowCauses') }}
{{ i18n.t('caMgLowCause1') }}
{{ i18n.t('caMgLowCause2') }}
{{ i18n.t('caMgLowCause3') }}
{{ i18n.t('caMgLowFixes') }}
{{ i18n.t('caMgLowFix1') }}
{{ i18n.t('caMgLowFix3') }}
{{ i18n.t('caMgLowFixWarning') }}
{{ i18n.t('caMgLowWhenToAct') }}
{{ i18n.t('caMgCommonMistakes') }}
{{ i18n.t('caMgMistake1Title') }}
{{ i18n.t('caMgMistake1Text') }}
{{ i18n.t('caMgMistake2Title') }}
{{ i18n.t('caMgMistake2Text') }}
{{ i18n.t('caMgMistake3Title') }}
{{ i18n.t('caMgMistake3Text') }}
{{ i18n.t('caMgTiming') }}
{{ i18n.t('caMgTimingCa') }}
{{ i18n.t('caMgTimingMg') }}
{{ i18n.t('caMgOneLiner') }}
{{ i18n.t('whatIsBoronLevel') }}
{{ i18n.t('boronYourCurrentLevel') }}
{{ i18n.formatNumber(modalData.boronPpm?.toFixed(2) || '0') }} ppm
{{ modalData.boronStatus.text }}
{{ i18n.t('boronTargetRange') }}
{{ i18n.t('boronThresholdsTitle') }}
{{ i18n.t('boronThreshold1') }}
{{ i18n.t('boronThreshold2') }}
{{ i18n.t('boronThreshold3') }}
{{ i18n.t('boronThreshold4') }}
{{ i18n.t('boronToxicityTitle') }}
{{ i18n.t('boronToxicitySymptom1') }}
{{ i18n.t('boronToxicitySymptom2') }}
{{ i18n.t('boronToxicitySymptom3') }}
{{ i18n.t('boronToxicitySymptom4') }}
{{ i18n.t('boronCausesTitle') }}
{{ i18n.t('boronCause1') }}
{{ i18n.t('boronCause2') }}
{{ i18n.t('boronCause3') }}
{{ i18n.t('boronCause4') }}
{{ i18n.t('boronFixesTitle') }}
{{ i18n.t('boronFix1') }}
{{ i18n.t('boronFix2') }}
{{ i18n.t('boronFix3') }}
{{ i18n.t('boronFix4') }}
{{ i18n.t('boronRecirculatingTitle') }}
{{ i18n.t('boronRecirculatingText') }}
{{ i18n.t('boronResearchNote') }}
Fertilizer Calculator
Language
English
ગુજરાતી (Gujarati)
हिन्दी (Hindi)
ಕನ್ನಡ (Kannada)
తెలుగు (Telugu)
मराठी (Marathi)
বাংলা - সাধু (Bengali Sadhu)
বাংলা - চলিত (Bengali Cholito)
தமிழ் (Tamil)
മലയാളം (Malayalam)
ਪੰਜਾਬੀ (Punjabi)
ଓଡ଼ିଆ (Odia)
অসমীয়া (Assamese)
भोजपुरी (Bhojpuri)
मैथिली (Maithili)
अवधी (Awadhi)
What would you like to do?
Choose a calculator mode based on what information you have.
Grams → PPM
Calculate what nutrient concentrations (PPM) you'll get from specific amounts of fertilizers.
Best for:
You have fertilizers weighed out and want to know the resulting nutrient levels in your solution.
PPM → Grams
Enter your target PPM values and get the exact fertilizer amounts needed to achieve them.
Best for:
You have specific PPM targets (e.g., from a recipe or plant requirements) and need to know how much of each fertilizer to use.
NPK Ratio → Grams
Enter nutrient ratios (like 3-1-2) and a target EC to get fertilizer amounts that match your desired balance.
Best for:
You know the nutrient ratio you want (e.g., for a specific growth stage) and want to scale it to your desired EC/strength.
Acidify Mix with PeKacid
Introduce PeKacid into your existing fertilizer mix for acidification, while keeping nutrient levels balanced.
Best for:
You have a recipe and want to add PeKacid for pH control while maintaining the same nutrient profile.
Stock Solution Maker
Create concentrated A/B stock solutions with dosing instructions for multiple target ratios and EC levels.
Best for:
You want to pre-mix concentrated stock solutions that can serve multiple growth stages by varying the dosing amounts.
{{ getStepIndicator('volume-step') }}
How much solution are you making?
Enter the total volume of water you'll be mixing your fertilizers into.
liters
Continue →
← Back
{{ getStepIndicator('calc-mode-step') }}
How do you want to enter values?
Choose between commercial fertilizer notation or pure elemental values.
Continue →
← Back
{{ getStepIndicator('ec-step') }}
What strength solution do you want?
Choose the EC (electrical conductivity) you want the mix to reach. It tells us how concentrated the nutrients should be, and we'll scale the fertilizer amounts to hit that strength for your batch.
0.2 mS/cm - Plain Water Supplement
0.4 mS/cm - Recovery/Flush
0.6 mS/cm - Fresh Clones/Cuttings
0.8 mS/cm - Rooted Cuttings
1.0 mS/cm - Seedlings/Young Plants
1.2 mS/cm - General Purpose
1.5 mS/cm - Vegetative Growth
1.8 mS/cm - Active Growth
2.0 mS/cm - Heavy Feeders
2.5 mS/cm - Flowering/Fruiting
3.0 mS/cm - Maximum (experienced growers)
{{ wizardECDescription }}
Continue →
← Back
{{ i18n.t('resultsPpm') }}
?
{{ item.label }}
{{ i18n.formatNumber((item.value || 0).toFixed(2)) }}
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('achievedEc') }} ?
{{ i18n.t('warningsAndRecommendations') }}
{{ warning.level === 'warning' ? '⚠️' : warning.level === 'error' ? '❌' : 'ℹ️' }} {{ warning.category }}
{{ warning.message }}
{{ i18n.t('nitrogenFormLabel') }}
{{ i18n.formatNumber(formulaResultsData.result.achieved.N_NH4.toFixed(1)) }} ppm NH₄-N
({{ i18n.formatNumber(formulaResultsData.nh4Percent.toFixed(1)) }}% {{ i18n.t('ofTotalN') }}),
{{ i18n.formatNumber(formulaResultsData.result.achieved.N_NO3.toFixed(1)) }} ppm NO₃-N
({{ i18n.formatNumber((100 - formulaResultsData.nh4Percent).toFixed(1)) }}% {{ i18n.t('ofTotalN') }})
, {{ i18n.formatNumber(formulaResultsData.result.achieved.N_Urea.toFixed(1)) }} ppm {{ i18n.t('ureaN') || 'Urea-N' }}
{{ i18n.t('targetVsAchieved') || 'Target vs Achieved' }}
{{ item.label }}
{{ i18n.formatNumber((item.achieved || 0).toFixed(2)) }} {{ item.status }}
{{ i18n.t('targetLabel') || 'Target:' }} {{ i18n.formatNumber(item.target.toFixed(2)) }}
{{ i18n.t('predictedEc') }} ?
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('warningsAndRecommendations') }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
{{ i18n.t('targetVsAchievedRatios') || 'Achieved PPM' }}
{{ item.label }}
{{ i18n.formatNumber((item.achievedPPM || 0).toFixed(2)) }} {{ item.status }}
{{ i18n.t('ratioLabel') || 'Ratio:' }} {{ item.userInput }} → {{ i18n.formatNumber((item.achievedRatio || 0).toFixed(2)) }}
{{ i18n.t('nitrogenFormLabel') }}
{{ i18n.formatNumber(reverseResultsData.result.achieved.N_NH4.toFixed(1)) }} ppm NH₄-N
({{ i18n.formatNumber(reverseResultsData.nh4Percent.toFixed(1)) }}% {{ i18n.t('ofTotalN') }}),
{{ i18n.formatNumber(reverseResultsData.result.achieved.N_NO3.toFixed(1)) }} ppm NO₃-N
({{ i18n.formatNumber((100 - reverseResultsData.nh4Percent).toFixed(1)) }}% {{ i18n.t('ofTotalN') }})
, {{ i18n.formatNumber(reverseResultsData.result.achieved.N_Urea.toFixed(1)) }} ppm {{ i18n.t('ureaN') || 'Urea-N' }}
{{ i18n.t('estimatedEC') }} ?
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('warningsAndRecommendations') }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
{{ i18n.t('stockSettings') || 'Stock Solution Settings' }}
{{ i18n.t('concentration') || 'Concentration' }}: {{ stockResultsData.settings?.concentrationFactor }}×
{{ i18n.t('tankVolume') || 'Tank Volume' }}: {{ stockResultsData.settings?.tankVolume }} L
{{ i18n.t('baselineEC') || 'Baseline EC' }}: {{ stockResultsData.settings?.baselineEC }} mS/cm
{{ i18n.t('maxDosing') || 'Max Dosing' }}: {{ stockResultsData.settings?.maxDosing }} mL/L
{{ tank.name || ('Tank ' + String.fromCodePoint(65 + tankIdx)) }}
({{ tank.description || '' }})
{{ i18n.getFertilizerName(fert) || fert.name }}
{{ i18n.formatNumber(fert.gPerL.toFixed(2)) }} g/L
({{ i18n.formatNumber((fert.gPerL * stockResultsData.settings?.tankVolume).toFixed(1)) }} g total)
{{ i18n.t('total') || 'Total' }}
{{ i18n.formatNumber(tank.fertilizers.reduce((sum, f) => sum + f.gPerL, 0).toFixed(2)) }} g/L
⚠️ {{ i18n.t('nearSolubilityLimit') || 'Near Solubility Limit' }}
{{ i18n.t('nearSolubilityLimitDesc') || 'Some fertilizers are near their solubility limit. Ensure complete dissolution.' }}
{{ i18n.t('dosingInstructions') || 'Dosing Instructions' }}
{{ i18n.t('dosingInstructionsDesc') || 'Add these amounts of each stock to your reservoir per liter of final solution:' }}
{{ i18n.t('target') || 'Target' }}
{{ i18n.t('targetEC') || 'EC' }}
{{ tank.name || ('Tank ' + String.fromCodePoint(65 + idx)) }}
{{ dosing.targetName }}
{{ dosing.ratio }}
{{ dosing.ec }} mS/cm
{{ i18n.formatNumber((dose || 0).toFixed(2)) }} mL/L
{{ i18n.t('targetResults') || 'Target Results' }}
{{ dosing.targetName }}
{{ i18n.t('targetECLabel') || 'Target EC' }}: {{ dosing.ec }} mS/cm
{{ i18n.t('achievedEC') || 'Achieved' }}: {{ i18n.formatNumber((dosing.predicted.EC || 0).toFixed(2)) }} mS/cm
{{ Math.abs(dosing.predicted.EC - dosing.ec) / dosing.ec < 0.05 ? '✓' : '~' }}
{{ i18n.t('achievedNutrients') || 'Achieved Nutrients' }} (ppm):
{{ nutrient }}
{{ i18n.formatNumber((dosing.predicted.nutrients[nutrient] || 0).toFixed(1)) }}
ratio: {{ dosing.predicted.ratio[nutrient] }}
{{ i18n.t('ionBalance') || 'Ion Balance' }}:
+ {{ i18n.formatNumber((dosing.predicted.ionBalance.cations || 0).toFixed(2)) }} meq/L
vs
− {{ i18n.formatNumber((dosing.predicted.ionBalance.anions || 0).toFixed(2)) }} meq/L
{{ i18n.t('imbalance') || 'Imbalance' }}: {{ i18n.formatNumber((dosing.predicted.ionBalance.imbalance || 0).toFixed(1)) }}%
{{ warning.level === 'warning' ? '⚠️' : warning.level === 'error' ? '❌' : 'ℹ️' }}
{{ warning.message }}
{{ nutrient }}:
target ratio {{ i18n.formatNumber((err.target || 0).toFixed(2)) }} →
achieved {{ i18n.formatNumber((err.achieved || 0).toFixed(2)) }}
({{ i18n.formatNumber(((err.error || 0) * 100).toFixed(1)) }}% off)
Required: {{ i18n.formatNumber((warning.details.required || 0).toFixed(1)) }} mL/L,
Max allowed: {{ i18n.formatNumber((warning.details.max || 0).toFixed(1)) }} mL/L
Target: {{ i18n.formatNumber((warning.details.target || 0).toFixed(2)) }} mS/cm,
Predicted: {{ i18n.formatNumber((warning.details.predicted || 0).toFixed(2)) }} mS/cm
{{ i18n.t('warningsAndRecommendations') }}
{{ warning.level === 'warning' ? '⚠️' : warning.level === 'error' ? '❌' : 'ℹ️' }} {{ warning.category }}
{{ warning.message }}
{{ nutrient }}:
target ratio {{ i18n.formatNumber((err.target || 0).toFixed(2)) }} →
achieved {{ i18n.formatNumber((err.achieved || 0).toFixed(2)) }}
({{ i18n.formatNumber(((err.error || 0) * 100).toFixed(1)) }}% off)
Required: {{ i18n.formatNumber((warning.details.required_gL || 0).toFixed(1)) }} g/L,
Max solubility: {{ i18n.formatNumber((warning.details.max_gL || 0).toFixed(0)) }} g/L
{{ i18n.t('acidifySuccessMessage') || 'Success! Your recipe has been adjusted to include PeKacid while maintaining nutrient balance.' }}
{{ i18n.t('acidifyNutrientChangeWarning') || 'Note: Other nutrients changed' }}
{{ i18n.t('acidifyNutrientChangeDetails', { changes: acidifyResultsData.nutrientChangesText }) || ('Reducing fertilizers to compensate for PeKacid also affected: ' + acidifyResultsData.nutrientChangesText + '. This is expected because those fertilizers provided multiple nutrients.') }}
{{ i18n.t('acidifyBeforeTitle') || 'Original Recipe' }}
{{ i18n.getFertilizerName(fert) }}
{{ i18n.formatNumber(fert.grams.toFixed(2)) }} {{ i18n.t('gramsShort') }}
{{ i18n.t('total') || 'Total' }}
{{ i18n.formatNumber(acidifyResultsData.beforeTotalGrams.toFixed(2)) }} {{ i18n.t('gramsShort') }}
{{ i18n.t('acidifyAfterTitle') || 'With PeKacid' }}
{{ i18n.getFertilizerName(fert) }}{{ fert.id === 'icl_pekacid_pk_acid' ? ' ✓' : '' }}
{{ i18n.formatNumber(fert.grams.toFixed(2)) }} {{ i18n.t('gramsShort') }}{{ fert.adjustment ? ' (' + (fert.adjustment > 0 ? '+' : '') + i18n.formatNumber(fert.adjustment.toFixed(2)) + ')' : '' }}
{{ i18n.t('total') || 'Total' }}
{{ i18n.formatNumber(acidifyResultsData.afterTotalGrams.toFixed(2)) }} {{ i18n.t('gramsShort') }}
{{ i18n.t('acidifyAdjustmentsTitle') || 'Adjustments Made' }}
{{ i18n.getFertilizerName(adj) }}:
{{ i18n.formatNumber(adj.originalGrams.toFixed(2)) }} {{ i18n.t('gramsShort') }} →
{{ i18n.formatNumber(adj.newGrams.toFixed(2)) }} {{ i18n.t('gramsShort') }}
({{ adj.reduction > 0 ? '-' : '+' }}{{ i18n.formatNumber(Math.abs(adj.reduction).toFixed(2)) }} {{ i18n.t('gramsShort') }})
{{ i18n.t('acidifyPpmComparisonTitle') || 'Nutrient Levels (PPM)' }}
{{ i18n.t('acidifyPpmComparisonDesc') || 'Values should remain the same before and after PeKacid addition.' }}
{{ item.label }}
{{ i18n.t('before') || 'Before' }}: {{ i18n.formatNumber(item.before.toFixed(1)) }}
{{ i18n.t('after') || 'After' }}: {{ i18n.formatNumber(item.after.toFixed(1)) }}
{{ i18n.t('diffLabel') || 'Diff' }}: {{ item.diff > 0 ? '+' : '' }}{{ i18n.formatNumber(item.diff.toFixed(1)) }}
{{ i18n.t('achievedEc') }} ?
{{ acidifyResultsData.failureReason || i18n.t('acidifyFailedMessage') || 'Cannot maintain the same nutrient profile with the requested PeKacid amount.' }}
{{ i18n.t('acidifyWhyFailed') || 'Why did this fail?' }}
{{ acidifyResultsData.failureDetails || i18n.t('acidifyFailedExplanation') || 'The PeKacid amount requested would add more P or K than can be compensated by reducing other fertilizers in your mix. Your recipe may not have enough P or K sources to reduce.' }}
{{ i18n.t('acidifySuggestions') || 'Suggestions' }}
{{ i18n.t('acidifySuggestion1') || 'Try a smaller amount of PeKacid' }}
{{ i18n.t('acidifySuggestion2') || 'Add more P or K sources to your original recipe' }}
{{ i18n.t('acidifySuggestion3') || 'Use the PPM to Grams calculator to build a new recipe with PeKacid included' }}
{{ i18n.t('acidifyOriginalRecipe') || 'Your Original Recipe' }}
{{ i18n.getFertilizerName(fert) }}
{{ i18n.formatNumber(fert.grams.toFixed(2)) }} {{ i18n.t('gramsShort') }}
{{ i18n.t('twoTankSeparationNote') }}
{{ i18n.t('targetVsAchieved') || 'Target vs Achieved' }}
{{ item.label }}
{{ i18n.formatNumber((item.achieved || 0).toFixed(2)) }} {{ item.status }}
{{ i18n.t('targetLabel') || 'Target:' }} {{ i18n.formatNumber(item.target.toFixed(2)) }}
{{ i18n.t('targetVsAchievedRatios') || 'Achieved PPM' }} ?
{{ item.label }}
{{ i18n.formatNumber((item.achievedPPM || 0).toFixed(2)) }} {{ item.status }}
{{ i18n.t('ratioLabel') || 'Ratio:' }} {{ item.userInput }} → {{ i18n.formatNumber((item.achievedRatio || 0).toFixed(2)) }}
{{ i18n.t('predictedEc') }} ?
{{ i18n.t('estimatedEC') }} ?
{{ i18n.t('predictedEc') }} ?
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
{{ i18n.t('warningsAndRecommendations') }}
{{ warning.category }}: {{ warning.message }}
{{ devLogsExpanded ? '▼' : '▶' }}
Developer Logs ({{ devLogs.length }})
Clear
Copy All
No logs yet. Run a calculation to see logs.
{{ log.time }}
{{ log.message }}
{{ i18n.t('resultsPpm') }}
?
{{ item.label }}
{{ i18n.formatNumber((item.value || 0).toFixed(2)) }}
ppm
{{ i18n.t('noteLabel') }} {{ i18n.t('oxideConversionNote') }}
{{ i18n.t('ionBalance') }}
?
{{ i18n.t('whatIsIonBalanceQuestion') }} {{ i18n.t('ionBalanceExplanationFull') }}
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('whatAreNutrientRatios') }} {{ i18n.t('nutrientRatioExplanationFull') }}
{{ i18n.t('achievedEc') }} ?
{{ i18n.t('warningsAndRecommendations') }}
{{ warning.level === 'warning' ? '⚠️' : warning.level === 'error' ? '❌' : 'ℹ️' }} {{ warning.category }}
{{ warning.message }}
{{ i18n.t('twoTankSeparationNote') }}
{{ i18n.t('warningsAndRecommendations') }}
{{ warning.category }}: {{ warning.message }}
{{ i18n.t('twoTankSeparationNote') }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
✓ {{ i18n.t('targetsSuccessfullyAchieved') }}
{{ i18n.t('allNutrientValuesWithinRange') }}
{{ i18n.t('targetVsAchievedRatios') }} ?
{{ i18n.t('nutrient') }}
{{ i18n.t('yourInput') }}
{{ i18n.t('achievedRatio') }}
{{ i18n.t('ppmAchieved') }}
{{ item.label }}
{{ i18n.t('ppmLabel') }}
{{ i18n.formatNumber(Number(item.userInput || 0).toFixed(1)) }} {{ i18n.t('ppmUnit') }}
{{ i18n.formatNumber(Number(item.userInput || 0).toFixed(2)) }}
{{ i18n.formatNumber(Number(item.achievedRatio || 0).toFixed(1)) }} {{ i18n.t('ppmUnit') }} {{ item.status }}
{{ i18n.formatNumber(Number(item.achievedRatio || 0).toFixed(2)) }} {{ item.status }}
{{ i18n.formatNumber(Number(item.achievedPPM || 0).toFixed(1)) }} {{ i18n.t('ppmUnit') }}
{{ i18n.t('elementalModeLabel') }} {{ i18n.t('elementalModeNote') }}
{{ i18n.t('elementalToOxideConversion') }}
{{ i18n.t('oxideModeLabel') }} {{ i18n.t('oxideModeNote') }}
{{ i18n.t('oxideToElementalConversion') }}
{{ i18n.t('nitrogenFormLabel') }}
{{ i18n.formatNumber(reverseResultsData.result.achieved.N_NH4.toFixed(1)) }} ppm NH₄-N
({{ i18n.formatNumber(reverseResultsData.nh4Percent.toFixed(1)) }}% {{ i18n.t('ofTotalN') }}),
{{ i18n.formatNumber(reverseResultsData.result.achieved.N_NO3.toFixed(1)) }} ppm NO₃-N
({{ i18n.formatNumber((100 - reverseResultsData.nh4Percent).toFixed(1)) }}% {{ i18n.t('ofTotalN') }})
{{ i18n.t('ionBalance') }} ?
{{ i18n.t('estimatedEC') }}
{{ i18n.t('nutrientRatioAnalysis') }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
{{ i18n.t('twoTankSeparationNote') }}
{{ i18n.t('nutritionalConsiderations') }}
{{ warning.category }}: {{ warning.message }}
v1.9.1